库的准备
要使用C语言连接mysql,需要使用mysql官网提供的connect库,可以去官网下载,由于我们要下载到 Linux 操作系统中,也可以使用如下指令进行安装库
bash
sudo apt-get install libmysqlclient-dev
MySQL连接C/C++的库通常会安装在/usr/include/mysql
目录下,您可以通过以下命令检查该目录下是否存在相关的头文件:
bash
ls /usr/include/mysql
库文件通常会安装在/usr/lib
或/usr/lib64
目录下,您可以通过以下命令检查该目录下是否存在相关的库文件:
bash
ls /usr/lib/mysql
ls /usr/lib64/mysql
不过这只是一般的情况,根据版本的不同机器的不同都有差异,其库文件安装的位置也不同,如果安装在非标准路径下,可以使用mysql_config
命令来获取正确的编译选项,从而了解到库文件安装的位置:
bash
mysql_config --cflags --libs
我的机器是Ubuntu系统,从显示的结果我们可以看出 -L 后跟着的是 /usr/lib/x86_64-linux-gnu,说明库文件位于/usr/lib/x86_64-linux-gnu下,由于其中文件过多就不展示,实际上我们编译时也可以直接使用 -L /usr/lib 。
现在我们 尝试链接mysql client,通过 mysql_get_client_info() 函数,来验证我们的引入是否成功。
cpp
#include<iostream>
#include <mysql/mysql.h>
using namespace std;
int main()
{
cout<< "mysql version:" << mysql_get_client_info() <<endl;
}
编译指令如下:
bash
g++ -o mytest testdb.cc -L /usr/lib -l mysqlclient
其中 -L 后指明了动态库的路径,-l 跟着所要链接的动态库,由于我们在包含头文件时写的是#include <mysql/mysql.h> ,所以不用再指明头文件的具体路径,因为头文件位于 /usr/include/mysql 路径下,而 /usr/include 已经添加到环境变量PATH中,如果包含头文件时写的是#include <mysql.h>,则编译时需要添加 -I /usr/include/mysql ,指明头文件所在路径。
运行结果如下,说明我们已经下载好MySQL连接C/C++的库。
mysql****接口介绍
mysql_init
cpp
MYSQL *mysql_init(MYSQL *mysql);
该函数用于初始化一个MySQL连接对象。
第一个参数 MYSQL 是 C api中一个非常重要的变量,里面内存非常丰富,有 port,dbname,charset等连接基本参数。
- 如果mysql是NULL指针,该函数将分配、初始化、并返回新对象。
- 如果mysql不是NULL指针,该函数将初始化对象,并返回对象的地址。
cpp
MYSQL* conn = mysql_create_conn(NULL);
mysql_real_connect
cpp
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网络部分是基于TCP/IP的)mysql_real_connect
用于尝试与运行在主机上的MySQL数据库引擎建立连接。在能够执行需要有效MySQL连接句柄结构的任何其他API函数之前,mysql_real_connect
必须成功完成。
mysql
:这应该是一个已经初始化的MYSQL
结构的地址。在调用mysql_real_connect
之前,必须调用mysql_init
来初始化MYSQL
结构。host
:主机名或IP地址。如果host
是NULL
或字符串"localhost"
,连接将被视为与本地主机的连接。user
:用户的MySQL登录ID。如果user
是NULL
或空字符串""
,用户将被视为当前用户。passwd
:用户的密码。db
:数据库名称。如果db
为NULL
,连接会将默认的数据库设为该值。port
:如果不是0,其值将用作TCP/IP连接的端口号。注意,host
参数决定了连接的类型。unix_socket
:如果不是NULL
,该字符串描述了应使用的套接字或命名管道。注意,host
参数决定了连接的类型。client_flag
:通常为0,但也能设置为特定标志的组合,以允许特定功能,如使用压缩协议、返回发现的行数而非受影响的行数等。
我们可以先使用如下代码来查看是否连接成功,该文件为 testdb.cc
cpp
#include<iostream>
#include <mysql/mysql.h>
using namespace std;
int main()
{
MYSQL* conn=mysql_init(nullptr);
if(conn==nullptr)
cout<<"mysql_init error"<<endl;
//链接数据库
mysql_real_connect(conn,"localhost","lbk","2162627569","connect",3306,nullptr,0);
if(conn==nullptr)
cout<<"mysql_real_connect error"<<endl;
else
cout<<"mysql_real_connect success"<<endl;
return 0;
}
编译指令
bash
g++ -o mytest testdb.cc -L /usr/lib -l mysqlclient
我们可以看到连接成功。
mysql_query
cpp
int mysql_query(MYSQL *mysql, const char *query);
参数:
mysql
:一个已经初始化的MYSQL
对象,表示与MySQL数据库的连接。query
:一个以空字符结尾的字符串,包含了要发送的SQL查询语句。
返回值:如果查询成功,函数返回0;如果发生错误,函数返回非零值。
例如我们向connect数据库中的stu表中插入数据
cpp
#include <iostream>
#include <mysql/mysql.h>
using namespace std;
int main()
{
MYSQL *conn = mysql_init(nullptr);
if (conn == nullptr)
cout << "mysql_init error" << endl;
// 链接数据库
mysql_real_connect(conn, "localhost", "lbk", "2162627569", "connect", 3306, nullptr, 0);
if (conn == nullptr)
cout << "mysql_real_connect error" << endl;
// 执行sql语句
const char *sql = "insert into stu values(1,'Tom')";
if (mysql_query(conn, sql) == 0)
cout << "insert success" << endl;
return 0;
}
运行程序后,我们可以在MySQL中看到stu表中插入的数据。
mysql_store_result
sql 执行完以后,如果是查询语句,我们当然还要读取数据,如果 update , insert等语句,那么就看下操作成功与否即可。我们就需要使用select语句来获取查询结果: 如果mysql_query返回成功,那么我们就通过mysql_store_result这个函数来读取结果。原型如下:
cpp
MYSQL_RES *mysql_store_result(MYSQL *mysql);
该函数将查询的全部结果读取到客户端,分配一个MYSQL_RES结构,并将结果置于该结构中,如果读取结果集失败,mysql_store_result也会返回Null指针。以下是 MYSQL_RES结构体的定义:
cpp
typedef struct st_mysql_res {
my_ulonglong row_count; // 结果集的行数
unsigned int field_count, current_field; // 结果集的列数和当前列
MYSQL_FIELD *fields; // 结果集的列信息
MYSQL_DATA *data; // 结果集的数据
MYSQL_ROWS *data_cursor; // 结果集的光标
MEM_ROOT field_alloc; // 内存结构
MYSQL_ROW row; // 非缓冲的时候用到
MYSQL_ROW current_row; // mysql_store_result 时会用到,当前行
unsigned long *lengths; // 每列的长度
MYSQL *handle; // mysql_use_result 会用
my_bool eof; // 是否为行为
} MYSQL_RES;
获得了结果后,我们可以接着调用以下函数来处理结果。
cpp
my_ulonglong mysql_num_rows(MYSQL_RES *res);//获取结果行数
unsigned int mysql_num_fields(MYSQL_RES *res);//获取结果列数
mysql_fetch_fields
cpp
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);//获取列的属性
MYSQL_FIELD
结构体是 MySQL C API 中用于表示查询结果集中的字段信息的结构体。它包含了字段的名称、类型、长度等元数据信息。以下是 MYSQL_FIELD
结构体的定义:
cpp
typedef struct st_mysql_field {
char *name; /* 字段名 */
char *org_name; /* 原始字段名,如果有别名 */
char *table; /* 字段所属的表名,如果字段是表中的一个字段 */
char *org_table; /* 原始表名,如果表名有别名 */
char *db; /* 表所在的数据库名 */
char *catalog; /* 表的目录名 */
char *def; /* 字段的默认值 */
unsigned long length; /* 字段的长度 */
unsigned long max_length; /* 字段在结果集中的最大长度 */
unsigned int name_length;
unsigned int org_name_length;
unsigned int table_length;
unsigned int org_table_length;
unsigned int db_length;
unsigned int catalog_length;
unsigned int def_length;
unsigned int flags; /* 字段的标志 */
unsigned int decimals; /* 字段的小数位数 */
unsigned int charsetnr; /* 字段的字符集编号 */
enum enum_field_types type; /* 字段的类型 */
void *extension;
} MYSQL_FIELD;
使用案例,列出stu表的列名:
cpp
#include <iostream>
#include <mysql/mysql.h>
using namespace std;
int main()
{
MYSQL *conn = mysql_init(nullptr);
if (conn == nullptr)
cout << "mysql_init error" << endl;
// 链接数据库
mysql_real_connect(conn, "localhost", "lbk", "2162627569", "connect", 3306, nullptr, 0);
if (conn == nullptr)
cout << "mysql_real_connect error" << endl;
// 执行sql语句
// const char *sql = "insert into stu values(1,'Tom')";
const char *sql1 = "insert into stu values(2,'Jane')";
mysql_query(conn, sql1);
const char *sql2 = "insert into stu values(3,'Jake')";
mysql_query(conn, sql2);
const char *sql3 = "select * from stu";
mysql_query(conn, sql3);
MYSQL_RES *res = mysql_store_result(conn);
int fnum = mysql_num_fields(res);
MYSQL_FIELD *field = mysql_fetch_fields(res);
for (int i = 0; i < fnum; i++)
{
cout << field[i].name << " ";
}
cout << endl;
return 0;
}
结果如下:
如果我们需要列的更多属性,可以按照结构体中的内容找出。
mysql_fetch_row
cpp
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
MYSQL_ROW结构体在 MySQL C API 中用于表示查询结果集中的一行数据。它实际上是一个指向字符串数组的指针,其中每个字符串对应结果集中的一个字段值。以下是 MYSQL_ROW 结构体的定义:
cpp
typedef char **MYSQL_ROW;
MYSQL_ROW
结构体没有显式定义的成员变量,因为它本质上是一个二级指针,指向一个字符串数组。数组中的每个元素都是一个以 null 结尾的字符串,代表结果集中的一个字段值。
mysql_close
cpp
void mysql_close(MYSQL *mysql);
mysql_close
函数用于关闭与MySQL数据库的连接。这个函数是MySQL C API的一部分,通常在完成数据库操作后调用,以释放与数据库连接相关的资源。