要使用C语言连接MySQL,需要使用MySQL官网提供的库。
如果我们使用的是Linux系统的话我们可以直接使用,下面的命令安装MySQL给我们提供的官方库:
sudo yum install mysql-community-devel
下载完以后我们可以在/usr/include/mysql/(其他系统可能会有差别)看到头文件:
ls /usr/include/mysql/
在/usr/lib64/mysql/看到对应的库:
ls /usr/lib64/mysql/
首先,进入MySQL官网,选择DOWNLOADS(下载),然后点击MySQL Community (GPL) Downloads。如下:
接下来选择Download Archives
最后选择适合自己平台的mysql connect库,然后点击下载就行了。如下:
因为这里我要在Linux服务器上使用,所以将其上传到云服务器,我准备将下载的库文件存放在一个名为mysqllib的目录下。
使用rz 命令将刚才下载的库文件上传到云服务器。如下:
rz
然后使用tar命令将压缩包解压到当前目录下。如下:
tar -xzf mysql-connector-c-6.1.11-linux-glibc2.12-x86_64.tar.gz
为了方便使用我们将名称更改一下:
mv mysql-connector-c-6.1.11-linux-glibc2.12-x86_64 mysql-connector-c
进入解压后的目录当中,可以看到有一个include子目录和一个lib子目录。如下:
其中,include目录下存放的一堆头文件。如下:
而lib目录下存放的就是动静态库。如下:
由于我们要使用的是动态库,所以当我们使用gcc编译时要使用-I命令后面跟对应的头文件路径,使用-L指定库的路径,使用-l连接具体的库。(这里为-l mysqlclient)
mysqlclient给我们提供了许多API,其官方手册中可以看到许多细节内容,此外还有一些关于mysqlclient库中一些结构体对象的含义可以看这里。
为了确保我们能够正常的将库引入进我们的代码中,我们可以先使用mysql_get_client_info()函数来进行测试。
代码如下:
#include#include int main() { const char* str = mysql_get_client_info(); printf("%s\n", str); return 0; }
为了方便后续重复编译源文件,可以在项目目录下创建一个Makefile,Makefile当中的内容如下:
说明:
编译运行成功:
从运行结果我们能够看出我们使用的客户端库版本是5.744,此外我们还可以使用ldd命令查看程序运行所需要的库:
至此库已经成功被引入,我们下面正式开始学习库接口的使用。
创建MYSQL对象
在连接数据库之前,需要先创建一个MySQL对象,创建MySQL对象的函数如下:
说明:
MYSQL对象中包含了各种信息,其类型定义如下:
连接数据库
创建完MySQL对象后就可以连接数据库了,连接数据库的函数如下:
参数说明:
返回值:
设置连接的编码格式
当我们使用mysql_real_connect建立好链接之后,获取英文字符是没有问题,但是如果是获取中文则是乱码,因为MySQL默认连接的编码格式采用latin1,所以我们需要设置连接的编码格式。
参数:
返回值:
关闭数据库连接
与数据库交互完毕后,需要关闭数据库连接释放资源,关闭数据库连接的函数如下:
说明:
比如使用如下代码连接我的MySQL服务器:
#include#include #include #include const char* host = "localhost"; const char* user = "qiling"; const char* password = "123456"; const char* db = "db1"; u_int32_t port = 3309; int main() { // 1.初始化MYSQL对象 MYSQL* my = mysql_init(NULL); if (!my) { perror("mysql_init fail: "); exit(errno); } // 2.连接MySQL服务器 if (!mysql_real_connect(my, host, user, password, db, port, NULL, 0)) { perror("mysql_real_connect fail: "); exit(errno); } // 3. 设置连接的编码格式 if (0 != mysql_set_character_set(my, "utf8")) { perror("mysql_set_character_set fail: "); exit(errno); } // 休眠10s,方便我们观察实验现象 sleep(10); // 4. 关闭连接,释放对象 mysql_close(my); return 0; }
我们编译运行此代码,同时让root用户使用show processlist命令查看登录状况。
可以看到,确实有一个叫qiling的用户连接了数据库,说明我们的连接成功了。
与数据库建立连接期间,就可以向MySQL服务器下发SQL请求,下发SQL请求的函数如下:
参数:
返回值:
测试表结构
这个账户表中我们设置主键为id并且自增,然后主要信息包含两个字段,name名称,balance余额。
通过下面的代码,我们进行测试:
#include#include #include #include const char* host = "localhost"; const char* user = "qiling"; const char* password = "123456"; const char* db = "db1"; u_int32_t port = 3309; int main() { // 1.初始化MYSQL对象 MYSQL* my = mysql_init(NULL); if (!my) { perror("mysql_init fail: "); exit(errno); } // 2.连接MySQL服务器 if (!mysql_real_connect(my, host, user, password, db, port, NULL, 0)) { perror("mysql_real_connect fail: "); exit(errno); } // 3. 设置连接的编码格式 if (0 != mysql_set_character_set(my, "utf8")) { perror("mysql_set_character_set fail: "); exit(errno); } // 4.下达SQL指令 // 4.1 增加信息 const char* sql = "insert into account(name, balance) values('Peter', 2398.4),('张三',3476.9)"; if (0 != mysql_query(my, sql)) { perror("mysql_query fail: "); exit(errno); } // 5. 关闭连接,释放对象 mysql_close(my); return 0; }
编译运行我们的代码,发现确实向表中新插入了两条数据,并且数据没有乱码。
.... const char* sql = "update account set name = 'Alex' where name='张三'"; ....
.... const char* sql = "delete from account where name = 'Peter'"; ...
至此为止我们现在增删改的操作都能够进行了!
数据存储
当我们对数据库中的数据进行增删改操作时,我们只关心操作有没有成功。
而对数据库中的数据进行查询操作时,除了需要知道有没有成功,还需要获取查询结果。
获取查询结果的函数如下:
说明:
MYSQL_RES变量中保存了查询得到的各种信息,其类型定义如下:
获取查询结果的行数
获取查询结果的行数的函数如下:
说明:
获取查询结果的列数
获取查询结果的列数的函数如下:
说明:
获取查询结果的列属性
说明:
mysql_fetch_fields函数将会返回一组MYSQL_FIELD对象,这组对象的地址是连续的,每个MYSQL_FIELD对象中保存着对应列的各种列属性,其类型定义如下:
获取查询结果中的一行数据
获取查询结果中的一行数据的函数如下:
说明:
MYSQL_ROW对象中保存着一行数据,这一行数据中可能包含多个字符串,对应就是这行数据中的多个列信息,因此MYSQL_ROW本质就是char**类型,我们将其可以当成一个char*的指针数组,其类型定义如下:
释放结果集
在前面我们说过MYSQL_RES变量的内存空间是malloc出来的,因此在使用完后需要调用mysql_free_result函数进行释放,否则会造成内存泄露。
mysql_free_result函数的原型如下:
只需要我们传递我们结果集对应的指针就行了
查询示例
为了让数据多一些,我们先多插入一些数据:
比如查询account表中的数据并进行打印输出。如下:
#include#include #include #include const char* host = "localhost"; const char* user = "qiling"; const char* password = "123456"; const char* db = "db1"; u_int32_t port = 3309; int main() { // 1.初始化MYSQL对象 MYSQL* my = mysql_init(NULL); if (!my) { perror("mysql_init fail: "); exit(errno); } // 2.连接MySQL服务器 if (!mysql_real_connect(my, host, user, password, db, port, NULL, 0)) { perror("mysql_real_connect fail: "); exit(errno); } // 3. 设置连接的编码格式 if (0 != mysql_set_character_set(my, "utf8")) { perror("mysql_set_character_set fail: "); exit(errno); } // 4.下达SQL指令 const char* sql = "select * from account"; if (0 != mysql_query(my, sql)) { perror("mysql_query fail: "); exit(errno); } // 5.获得存储结果 MYSQL_RES* my_res = mysql_store_result(my); // 5.1获得结果集中的行数 my_ulonglong rows = mysql_num_rows(my_res); // 5.2获得结果集中的列数 u_int32_t column = mysql_num_fields(my_res); // 5.3获得结果集中的字段属性 MYSQL_FIELD* filed_array = mysql_fetch_fields(my_res); // 5.4获取结果集中的数据,并进行打印 // 打印字段的属性 for (int i = 0; i < column; i++) { printf("%s\t", filed_array[i].name); } printf("\n"); printf("----------------------------\n"); // 打印字段的数据 for (int i = 0; i < rows; i++) { MYSQL_ROW row_data = mysql_fetch_row(my_res); for (int j = 0; j < column; j++) { printf("%s\t", row_data[j]); } printf("\n"); } // 6.释放结果集 mysql_free_result(my_res); // 7. 关闭连接,释放对象 mysql_close(my); return 0; }
对于事务的操作我们也可以使用mysql_query()函数进行开启一个事务,然后进行处理事务,下面我们介绍一些关于控制事务操作的一些API。
设置事务提交模式
参数:
mysql,我们使用mysql_init()函数创建出来的mysql对象
如果 mode 为 1,则将自动提交模式设置为 on,如果 mode 为 0,则将自动提交模式设置为 off。
返回值:
提交事务
参数:
返回值:
事务回滚
参数:
返回值:
返回错误的描述
参数:
返回值
返回错误的编号
参数:
返回值
下面的代码我们
根据代码我们最后插入的数据应该只有smith,8907.6,这是我们表的初始状态:
#include#include #include #include const char* host = "localhost"; const char* user = "qiling"; const char* password = "123456"; const char* db = "db1"; u_int32_t port = 3309; int main() { // 1.初始化MYSQL对象 MYSQL* my = mysql_init(NULL); if (!my) { perror("mysql_init fail: "); exit(errno); } // 2.连接MySQL服务器 if (!mysql_real_connect(my, host, user, password, db, port, NULL, 0)) { perror("mysql_real_connect fail: "); exit(errno); } // 3. 设置连接的编码格式 if (0 != mysql_set_character_set(my, "utf8")) { perror("mysql_set_character_set fail: "); exit(errno); } // 4.下达SQL指令 开启事务 mysql_autocommit(my, 1); mysql_query(my, "begin"); mysql_query(my, "insert into account(name, balance) values('smith', 3478.9)"); mysql_query(my, "update account set balance=8907.6 where name='smith'"); mysql_commit(my); mysql_query(my, "begin"); mysql_query(my, "insert into account(name, balance) values('lisa', 4588.7)"); mysql_rollback(my); // 5. 关闭连接,释放对象 mysql_close(my); return 0; }
最后的运行结果符合我们的预期:
上一篇:【数据结构】链表面试题