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: 可以从 Yum, APT, SuSE 仓库获得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 --libs 和 ldd 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数据库,以及进行数据添加
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的例子
参考:
#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。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探