C++ MySQL連接及增刪改查操作


一、使用准備

環境:CentOS 7.6和Ubuntu 16.04,MySQL 5.7

C++ MySQL連接相關庫下載

下載地址:MySQL Community Downloads

有兩種選擇,C API和Connector/C++,貌似C API簡單一點,Connector/C++比較規范,和Java JDBC接口一致。這里選擇C API

翻譯一下:

C API(libmysqlclient)是用於C開發的客戶端庫:

對於C語言和SQL:

  - 適用於MySQL 8.0、5.7、5.6、5.5

  - 我們建議使用MySQL 8.0 C API

C API(libmysqlclient)包含在MySQL 8.0中(其他版本也可以在其安裝文件夾中找到,通過某些特殊手段安裝的可能就沒有)

Linux:可從MySQL Community Server下載頁面獲得Client Utilities Package

Repos: 可以從 YumAPTSuSE 倉庫獲得Client Utilities Package

Windows:可從Windows Installer獲得Client Utilities Package

以前的GA版本可從MySQL Product Archives中獲得

在線文檔地址:MySQL C API

翻到C API在線文檔查看其使用說明:

該文檔說明了如何在Linux上編譯MySQL客戶端。請仔細閱讀,比如使用gcc編譯器,注意:以下部分均復制自官方文檔,為求准確,建議瀏覽官方文檔原文

1、引用頭文件:

編譯使用MySQL頭文件的客戶端程序時,可能需要指定-I選項,以便編譯器可以找到它們。例如,如果頭文件安裝在 /usr /local/mysql/include 中,請在compile命令中使用以下選項:

-I/usr/local/mysql/include

2、鏈接庫文件

您可以將代碼與動態或靜態MySQL C客戶端庫鏈接。動態庫的基本名稱為libmysqlclient,后綴因平台而異(例如,對於Linux為.so,對於macOS為.dylib)。在所有平台上,靜態庫均名為libmysqlclient.a。

必須使用link命令中的-lmysqlclient選項鏈接MySQL客戶端。您可能還需要指定-L選項,以告知鏈接器在哪里可以找到該庫。例如,如果該庫安裝在/usr/local/mysql/lib中,請在鏈接命令中使用以下選項:

-L/usr/local/mysql/lib -lmysqlclient

路徑名稱在您的系統上可能有所不同。根據需要調整-I和-L選項。

為了使在Unix上編譯MySQL程序更簡單,請使用mysql_config腳本。請參見Section 4.7.1, “mysql_config — Display Options for Compiling

mysql_config顯示編譯或鏈接所需的選項:

mysql_config --cflags
mysql_config --libs

您可以在命令行中使用反引號使用 mysql_config ,以包含它為特定選項生成的輸出。例如,要編譯和鏈接MySQL客戶端程序,請使用 mysql_config ,如下所示:

gcc -c `mysql_config --cflags` progname.c
gcc -o progname progname.o `mysql_config --libs`

詳情請閱讀mysql-config使用文檔

在Unix上,默認情況下鏈接使用動態庫。要鏈接到靜態客戶端庫,請將其路徑名添加到link命令。例如,如果該庫位於/usr/local/mysql/lib中,則像這樣鏈接:

gcc -o progname progname.o /usr/local/mysql/lib/libmysqlclient.a

或使用mysql_config提供庫的路徑:

gcc -o progname progname.o `mysql_config --variable=pkglibdir`/libmysqlclient.a

mysql_config 當前不提供列出靜態鏈接所需的所有庫的方法,因此可能有必要在鏈接命令上命名其他庫(例如,在Solaris上為-lnsl -lsocket)。要了解要添加哪些庫,請使用 mysql_config --libsldd libmysqlclient.so(或macOS上的 otool -L libmysqlclient.dylib)。

pkg-config可以代替mysql_config來獲取信息,例如編譯MySQL應用程序所需的編譯器標志或鏈接庫。例如,以下幾對命令是等效的:

mysql_config --cflags
pkg-config --cflags mysqlclient

mysql_config --libs
pkg-config --libs mysqlclient

關於 pkg-config 使用請自行百度,文檔比較多。

3、解決鏈接到MySQL客戶端庫的問題

MySQL客戶端庫包括內置的SSL支持。在鏈接時無需指定-lssl或-lcrypto。這樣做實際上可能導致運行時出現問題。

如果鏈接器找不到MySQL客戶端庫,則對於以mysql_開頭的符號,您可能會收到未定義的引用錯誤,例如以下所示:

/tmp/ccFKsdPa.o: In function `main':
/tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'
/tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'
/tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'

您應該能夠通過在鏈接命令的末尾添加 -Ldir_path -lmysqlclient 來解決此問題,其中 dir_path 表示客戶端庫所在目錄的路徑名。要確定正確的目錄,請嘗試以下命令:

mysql_config --libs

mysql_config 的輸出可能指示在鏈接命令上也應指定其他庫。您可以使用反引號將mysql_config輸出直接包含在編譯或鏈接命令中。例如:

gcc -o progname progname.o `mysql_config --libs`

如果在鏈接時發生錯誤,即未定義下限符號,請通過在編譯/鏈接行的末尾添加-lm來鏈接至數學庫。同樣,如果對於系統上應該存在的其他功能(例如connect())出現未定義的引用錯誤,請查看手冊頁中所涉及的功能,以確定應將哪些庫添加到鏈接命令中。

如果對於系統中不存在的函數,出現諸如以下的未定義引用錯誤,則通常意味着您的MySQL客戶端庫是在與您的系統不100%兼容的系統上編譯的:

mf_format.o(.text+0x201): undefined reference to `__lxstat'

在這種情況下,您應該下載最新版本的MySQL的源發行版,然后自己編譯MySQL客戶端庫。請參見Section 2.9, “Installing MySQL from Source”.

二、使用demo

在Ubuntu16.04上:

MySQL是直接使用apt-get安裝的,默認版本為5.7.30,測試一下mysql_config:

qb@qb-desktop:/usr$ mysql_config --cflags
-I/usr/include/mysql 
qb@qb-desktop:/usr$ mysql_config --libs
-L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -lrt -lssl -lcrypto -ldl
qb@qb-desktop:/usr$ which mysql_config
/usr/bin/mysql_config
qb@qb-desktop:/usr$ mysql_config --version
5.7.30
qb@qb-desktop:/usr$

注意:如果mysql_config不存在,按提示安裝即可。

在CentOS 7上:

mysql_config不存在,yum也無法安裝,這上面的MySQL是通過第三方rpm源安裝的。搜索一下:發現沒有頭文件

[root@jxh ~]# find / -name mysql_config
[root@jxh ~]# whereis mysql
mysql: /usr/bin/mysql /usr/lib64/mysql /usr/share/mysql /usr/share/man/man1/mysql.1.gz
[root@jxh ~]# cd /usr/lib64/mysql/
[root@jxh mysql]# ls
libmysqlclient_r.so.18      libmysqlclient.so.18      libmysqlclient.so.20       mecab
libmysqlclient_r.so.18.1.0  libmysqlclient.so.18.1.0  libmysqlclient.so.20.3.16  plugin

發現只有動態庫,按照 Centos下查看mysql的版本 查看版本為 5.7.29

所以把Ubuntu上的頭文件和庫文件拷貝過來使用(我的開發環境搭載CentOS 7上)應該是可以的。

在Ubuntu上 /usr/lib/x86_64-linux-gnu查看mysq庫文件

和CentOS 7上 5.7.29版本的基本一致,這里選擇把 libmysqlclient.a靜態庫和/usr/include/mysql下的頭文件都拷過去。

然后參照以下文章進行調用,測試通過

[1] VS2017項目中使用代碼連接MySQL數據庫,以及進行數據添加

[2] C++實現對MySQL數據庫的連接,以及增刪改查

Makefile文件如下:

PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))

# PROJECT_ROOT = /root/eclipse-workspace/mysql_c_demo/

# 中間文件, $(PROJECT_ROOT)*.o
OBJS = mysql_c_demo.o MySQLManager.o

# 目標文件名
TARGET = mysql_c_demo

# 編譯器設置
CXXFLAGS += -std=c++17 -flto

# 頭文件路徑
INCLUDE = -I$(PROJECT_ROOT)include/mysql

# 鏈接庫路徑
LDFLAGS = -L$(PROJECT_ROOT)lib

# 鏈接庫名
LIBS = -lmysqlclient -lpthread -lz -lm -lrt -lssl -lcrypto -ldl

# 指定運行時的動態庫文件路徑
#RPATH = -Wl,-rpath=../lib

# 宏定義
# DEFS = -NO_USE_SSL

# debug or release設置
ifeq ($(BUILD_MODE),debug)
    CXXFLAGS += -g
else ifeq ($(BUILD_MODE),run)
    CXXFLAGS += -O3
else
    $(error Build mode $(BUILD_MODE) not supported by this Makefile)
endif


all:    $(TARGET)

# 此處 $@ 表示目標文件集,即iot_servers, $^表示目標依賴集,即$(OBJS)
mysql_c_demo:    $(OBJS)
    $(CXX) -o $@ $^ $(LDFLAGS) $(LIBS) $(RPATH)

# %.o表 示所有以.o結尾的文件,%.cpp 表示所有以.cpp結尾的文件
#  $@ 表示目標集,也就是*.o文件,$<  表示所有的依賴目標集,即*.c文件(見Makefile自動化變量部分)
%.o:    $(PROJECT_ROOT)%.cpp
    $(CXX) -c $(CXXFLAGS) $(INCLUDE) -o $@ $<

.PHONY: clean
clean:
    rm -fr mysql_c_demo $(OBJS)

該文件為eclipse項目生成,其中有些變量在普通環境下不存在,刪掉或寫成自己的路徑即可。

三、問題

C API 默認使用 openssl 1.0版本,而我的項目中其他庫必須依賴openssl 1.1版本,導致無法鏈接進去(TMD),所以又改用  Connector/C++。

四、 Connector/C++

如下是使用JDBC API的例子

參考:

官方文檔

MySql Connector/C++8簡介

使用Connector/C++操作MySQL

MySQL connector/C++

#include <mysql/jdbc.h>
#include <iostream>

using namespace std;

int main(int argc, char **argv) {

    // 驅動
    sql::mysql::MySQL_Driver *driver = nullptr;
    // 連接
    sql::Connection *con = nullptr;
    // 數據庫操作執行對象
    sql::Statement *state = nullptr;
    // 結果對象
    sql::ResultSet *result = nullptr;

    // 初始化驅動
    driver = sql::mysql::get_mysql_driver_instance();
    if (driver == nullptr)
    {
        cout << "driver is null" << endl;
    }
    // 建立連接
    con = driver->connect("tcp://127.0.0.1:3306", "root", "JiXiaohua@5712");
    if (con == NULL)
    {
        cout << "conn is null" << endl;
        return -1;
    }
    cout << "connect suceess" << endl;

    // 創建數據庫操作執行對象
    state = con->createStatement();
    // use database
    state->execute("use c_mysql_test");

    // 執行查詢
    // 查詢
    result = state->executeQuery("select * from u_test where 1=1");

    // 輸出查詢
    cout << "id" << "\t\t" << "name" << "\t\t" << "age" << "\t\t" << "comment" << endl;
    while(result->next())
    {
        int id = result->getInt("id");
        string name = result->getString("name");
        int age = result->getInt("age");
        string comment = result->getString("comment");
        cout << id << "\t\t" << name << "\t\t" << age << "\t\t" << comment << endl;
    }

    // 釋放對象
    delete state;
    delete con;


    return 0;
}

完全的Java jdbc風格。

JDBC API的依賴庫太大了,官方文檔說了還可以使用X DevAPI and X DevAPI for C。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM