MYSQL 对 C/C++ 提供了 MYSQL 库用于操作数据库,Centos7 需要先行安装对应的文件:sudo yum install mysql-devel

使用 g++ 编译使用了该库的程序时需要加上 -L /usr/lib64/mysql -lmysqlclient

1. 建立 MYSQL 操作句柄

操作 MYSQL 需要使用库里提供的操作句柄,即一个 MYSQL 结构体。这个操作句柄几乎在所有接口函数中都要用到。

该句柄在使用前需要初始化,对应的接口函数为:

MYSQL* mysql_init(MYSQL* mysql)

如果参数 mysql 为空指针,则函数建立并初始化一个 MYSQL 变量,并返回其指针。如果参数为一个指向 MYSQL 结构体的指针,则函数对其进行初始化,并返回这个指针。

下面是使用示例:

MYSQL* connect_fd = mysql_init(nullptr);

2. 连接数据库

连接数据库的接口函数为:

MYSQL* mysql_real_connect(MYSQL* mysql, const char* host, const char* user, const char* passwd, const char* db, unsigned int port, const char* unix_socket, unsigned long client_flag)

其中,mysql 为操作句柄,host 为数据库所在主机的 IP ,user 为连接的数据库用户,passwd 为这个用户的密码,db 是要连接的数据库名,port 为连接的主机的端口,unix_socket 通常为空指针,client_flag 定义了一些额外的选项,通常置 0 。最后两个参数的具体使用可以查看上面的文档链接。

调用成功返回操作句柄,即第一个参数,否则为空指针。

下面是使用示例:

mysql_real_connect(connect_fd, "localhost", "root", "", "db_name", 3306, nullptr, 0);

3. 设置当前连接使用的字符集

mysql 中字符集是个要注意的地方。MYSQL 库提供了设置当前连接使用的字符集的接口函数

int mysql_set_character_set(MYSQL* mysql, const char* csname)

建议直接设成 utf-8

mysql_set_character_set(connect_fd, "utf8");

4. 执行 SQL 语句

执行 MYSQL 语句的接口函数如下:

int mysql_query(MYSQL* mysql, const char* stmt_str)

其中 stmt_str 为要执行的 SQL 语句。注意这里的 SQL 语句的末尾不能有 ;

调用成功返回 0 ,失败返回非零值。

示例如下:

char sql[2048] = { 0 };
sprintf(sql, "INSERT INTO tb_name values(%d, %d, %d)", 1, 2, 3);

if(mysql_query(connect_fd, sql)) {
    cout << "Error: mysql_query() failed!" << endl;
}

5. 查询 SQL 结果

查询结果

假如你执行的 SQL 语句会返回结果,例如 SELECT 语句,那么可以用下面的接口函数来接受结果:

MYSQL_RES* mysql_store_result(MYSQL* mysql)

其中 MYSQL_RES 结构体用于存储 SQL 语句执行的结果,这个结果被称为结果集(result set)。

在执行了所有可能返回查询结果的 SQL 语句(SELECTSHOWDECRIBEEXPLAINCHECK TABLE)后,都必须执行 mysql_store_result()mysql_use_result()。在最后也必须调用下一节介绍的接口函数去释放结果集。

如果调用成功,函数返回指向结果集的指针,否则返回空指针。注意返回空指针可能是因为该 SQL 语句就不返回结果(例如 INSERT),或者是函数内部出错。

如果 SQL 查询结果里没有一行数据(例如没有任何一条 SQL 数据匹配到你的查询条件),则返回的结果集为空结果集。注意空结果集和空指针是不一样的。

查看结果的行数和列数

假如函数返回了正确的结果集,你可以用下面两个接口函数来查看结果集中的行数和列数:

my_ulonglong mysql_num_rows(MYSQL_RES* result)
unsigned int mysql_num_fields(MYSQL_RES* result)

取出一行结果

下面的接口函数用于从结果集中取出一行结果:

MYSQL_ROW mysql_fetch_row(MYSQL_RES* result)

注意每调用一次这个函数,下次返回的结果就是下一行数据。如果所有行都取出后,再次调用该函数返回空指针。

MYSQL_ROW 结构用于表示一行结果,这个结构其实是一个字符串数组,例如我看源码里 MYSQL_ROW 其实就是 char ** typedef 来的。数组的长度就是查询结果的列数。

当前行中每一列的具体长度

而下面这个函数用于获取当前行中每一列的长度,即上一步返回的 MYSQL_ROW 数组中每个字符串的长度。

unsigned long* mysql_fetch_lengths(MYSQL_RES* result)

该函数的返回值也是一个数组,数组长度就是列的个数。

通过这一字段可以准确判断某个字段的长度,正常情况下 MYSQL_ROW 中每个字符串结尾都有 \0,无需额外判断这个字符串的长度,但假如其中存储的是二进制数据(即\0也可能是数据)就必须得通过这个函数判断字符串的真实长度,再进行后续操作。

假如数据库中某个字段的值为空,则 MYSQL_ROW 数组中对应的字符串为空字符串 ,且 mysql_fetch_lengths() 返回的数组中对应的长度为 0 。但假如数据库中某个字段的值为 NULL ,则 MYSQL_ROW 数组中对应的字符串为空指针,而长度同样为 0 。注意区分两者的区别。

下面的示例应用了这一节介绍的接口函数:

MYSQL_RES* my_res = mysql_store_result(connect_fd);
unsigned int rows = mysql_num_rows(my_res);
unsigned int cols = mysql_num_cols(my_res);
MYSQL_ROW my_row;

for(int i = 0; i < rows; i++) {
    my_row = mysql_fetch_row(my_res);
    for(int j = 0; j < cols; j++) {
        cout << my_row[j] << endl;
    }
}

6. 释放结果集

在使用完结果集后,必须调用下面的接口函数去释放结果集占用的内存,注意 MYSQL_RES 是一个黑盒结构,不能由用户自行释放。

void mysql_free_result(MYSQL_RES* result)

7. 关闭操作句柄

在使用完后需要调用下面的接口函数来关闭操作句柄:

void mysql_close(MYSQL* mysql)

如果操作句柄是由 mysql_init() 分配的空间,则同时空间也被释放。

Last modification:March 29th, 2020 at 10:15 pm