MySQL库的引入
我们使用C接口库来进行连接,要正确使用,我们需要做一些准备工作:引入MySQL库
第一种方法:手动从 MySQL 官网下载源码 / 预编译包,自行制作 / 配置库
使用mysql官网提供的库,去官网下载。
预编译版 .tar.gz 包 :可以直接解压使用(无需编译)
这种包是官方已经在对应 Linux 架构(如 x86_64)下编译好的成品,解压后直接包含 include(头文件)、lib(库文件)、bin(可执行文件)目录,无需再执行 cmake 编译流程,直接拷贝到目标目录即可使用。
具体步骤:
- 下载对应架构的预编译 .tar.gz 包后,解压到自定义目录:
bash
# 解压预编译包到 /usr/local 目录(系统级目录,方便后续引用)
sudo tar -zxvf mysql-connector-c-8.0.36-linux-glibc2.28-x86_64.tar.gz -C /usr/local/
- 重命名目录,方便后续引用
bash
sudo mv /usr/local/mysql-connector-c-8.0.36-linux-glibc2.28-x86_64 /usr/local/mysql-c-api
- 验证解压结果:进入目录后,能看到完整的 include 和 lib 目录,说明可以直接使用:
bash
# 查看目录结构
ls /usr/local/mysql-c-api/
# 预期输出:bin include lib LICENSE man README
- 编译 C 程序时,手动指定头文件和库文件路径即可
bash
gcc mysql_test.c -o mysql_test \
-I/usr/local/mysql-c-api/include \ # 指定头文件路径
-L/usr/local/mysql-c-api/lib \ # 指定库文件路径
-lmysqlclient # 链接mysql客户端库
当然也可以放到系统的头文件目录和库目录,编译时就不用指定头文件路径和库文件路径了。
注意:如果下载的是源码包(后缀为 .tar.gz),需要手动编译安装(依赖 gcc、cmake 环境,需提前安装)。
第二种方法:Linux(Ubuntu)下通过 apt 命令自动下载安装(最简单)
bash
# 更新软件源
sudo apt update
# 核心命令:安装mysql客户端库和开发文件(头文件+库文件)
sudo apt install libmysqlclient-dev -y
安装完成后,系统会自动将头文件和库文件放到默认路径:
- 头文件:
/usr/include/mysql/(包含 mysql.h 等核心头文件) - 库文件:
/usr/lib/x86_64-linux-gnu/(包含 libmysqlclient.so 等动态库、libmysqlclient.a 静态库)
无需手动配置路径,编译 C 程序时直接链接即可。
测试
通过 mysql_get_client_info() 函数,来验证我们的引入是否成功
cpp
#include <iostream>
#include <mysql/mysql.h>
int main()
{
std::cout << "mysql client version: " << mysql_get_client_info() << std::endl;
return 0;
}
syb@VM-8-5-ubuntu:~/mysqltest$ g++ -o mytest test.cc -lmysqlclient
syb@VM-8-5-ubuntu:~/mysqltest$ ./mytest
mysql client version: 8.0.44 --运行成功
至此引入库的工作已经做完,接下来就是熟悉接口
mysql接口介绍
官方文档:www.mysql.com
找到C接口的文档
文档介绍
初始化mysql_init()
要使用库,必须先进行初始化。
cpp
MYSQL *mfp = mysql_init(nullptr)
关闭mysql链接mysql_close
cpp
void mysql_close(MYSQL *sock);
cpp
int main()
{
MYSQL *my = mysql_init(nullptr);
if(nullptr == main)
{
std::cerr << "init MySQL error" << std::endl;
return 1;
}
mysql_close(my);
return 0;
}
链接数据库mysql_real_connect()
初始化完毕之后,必须先链接数据库,在进行后续操作。(mysql网络部分是基于TCP/IP的)
cpp
MYSQL *mysql_real_connect(MYSQL *mysql, //初始化创建的句柄
const char *host, //用户IP
const char *user, //登录的用户
const char *passwd, //用户密码
const char *db, //用户访问的数据库
unsigned int port, //端口号
const char *unix_socket,
unsigned long clientflag);
//建立好链接之后,获取英文没有问题,如果获取中文是乱码:
//设置链接的默认字符集是utf8,原始默认是latin1
mysql_set_character_set(myfd, "utf8");
第一个参数 MYSQL是 C api中一个非常重要的变量(mysql_init的返回值),里面内存非常丰富,有port,dbname,charset等连接基本参数。它也包含了一个叫 st_mysql_methods的结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。
例子:
cpp
#include <iostream>
#include <string>
#include <mysql/mysql.h>
const std::string host = "127.0.0.1";
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = 3306;//mysqld启动的默认端口是3306,所以连接也用这个
int main()
{
MYSQL *my = mysql_init(nullptr);
if (nullptr == my)
{
std::cerr << "init MySQL error" << std::endl;
return 1;
}
if(mysql_real_connect(my,host.c_str(),user.c_str(),passwd.c_str(),db.c_str(),port,nullptr,0)==nullptr)
{
std::cerr << "connect MySQL error" << std::endl;
return 2;
}
std::cout <<"connect success"<<std::endl;
mysql_close(my);
return 0;
}
下发mysql命令mysql_query
cpp
int mysql_query(MYSQL *mysql, const char *q);
第二个参数为要执行的sql语句,如"select * from table"。
返回值,成功返回0,失败返回非0。
例子:
cpp
std::string sql = " insert into user (name, age, telphone) values ('tom', 12, '123456789')";
int n = mysql_query(my, sql.c_str());
if (n == 0)
std::cout << sql << std::endl;
else
std::cout << sql << "failed" << std::endl;
cpp
#include <iostream>
#include <string>
#include <mysql/mysql.h>
const std::string host = "127.0.0.1";
const std::string user = "connector";
const std::string passwd = "syb020913";
const std::string db = "conn";
const unsigned int port = 3306; // mysqld启动的默认端口是3306,所以连接也用这个
int main()
{
MYSQL *my = mysql_init(nullptr);
if (nullptr == my)
{
std::cerr << "init MySQL error" << std::endl;
return 1;
}
if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
{
std::cerr << "connect MySQL error" << std::endl;
return 2;
}
std::cout << "connect success" << std::endl;
// 建立好链接之后,获取英文没有问题,但是获取中文可能是乱码
// 设置链接的默认字符集是utf8,原始默认是latin1
mysql_set_character_set(my, "utf8");//这时候就可以向数据库插入中文了
std::string sql;
while (true)
{
std::cout << "MySQL>> ";
if (!std::getline(std::cin, sql) || sql == "quit")
{
std::cout << "bye!" << std::endl;
break;
}
int n = mysql_query(my, sql.c_str());
if (n == 0)
{
std::cout << sql << " success: " << n << std::endl;
}
else
{
std::cerr << sql << " failed: " << n << std::endl;
}
}
mysql_close(my);
return 0;
}
获取执行结果mysql_store_result
sql执行完以后,如果是查询语句 ,我们当然还要读取数据,如果update,insert等语句,那么就看下操作成功与否即可。我们来看看如何获取查询结果: 如果mysql_query返回成功,那么我们就通过mysql_store_result这个函数来读取结果。原型如下:
cpp
MYSQL_RES *mysql_store_result(MYSQL *mysql);
同时该函数会返回MYSQL_RES 这样一个变量,该变量主要用于保存查询的结果。
- 成功返回MYSQL_RES指针
- 失败返回null。
注意 :该函数malloc了一片内存空间来存储查询过来的数据,所以我们一定要记的 free(result) ,不然是肯定会造成内存泄漏的。
例子:
cpp
MYSQL_RES *res = mysql_store_result(my);
if(nullptr == my)
{
std::cerr<<"mysql_store_result error"<<std::endl;
return 4;
}
mysql_free_result(res);//不要忘记释放
执行完mysql_store_result以后,其实数据都已经在MYSQL_RES 变量中了,下面的api基本就是读取MYSQL_RES 中的数据。
读取MYSQL_RES
获取结果行数mysql_num_rows
cpp
my_ulonglong mysql_num_rows(MYSQL_RES *res);
获取结果列数mysql_num_fields
cpp
unsigned int mysql_num_fields(MYSQL_RES *res);
获取结果内容mysql_fetch_row
cpp
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
它会返回一个MYSQL_ROW变量,MYSQL_ROW其实就是char**,当成二维数组使用就行。
关于MYSQL_RES 的结构
里面有个成员变量MYSQL_ROW,存储着查询结构的数据,本质上可以理解为一个二维数组,MYSQL_RES 维护一块开辟的空间,将MySQL输出的数据保存起来,全部当成字符串。

cpp
MYSQL_ROW line;
for (int i = 0; i < nums; i++)
{
line = mysql_fetch_row(res);
for (int j = 0; j < fields; j++)
{
cout << line[j] << " ";
}
cout << endl;
}
例子:
cpp
#include <iostream>
#include <string>
#include <mysql/mysql.h>
const std::string host = "127.0.0.1";
const std::string user = "connector";
const std::string passwd = "syb020913";
const std::string db = "conn";
const unsigned int port = 3306; // mysqld启动的默认端口是3306,所以连接也用这个
int main()
{
MYSQL *my = mysql_init(nullptr);
if (nullptr == my)
{
std::cerr << "init MySQL error" << std::endl;
return 1;
}
if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
{
std::cerr << "connect MySQL error" << std::endl;
return 2;
}
std::cout << "connect success" << std::endl;
// 建立好链接之后,获取英文没有问题,但是获取中文可能是乱码
// 设置链接的默认字符集是utf8,原始默认是latin1
mysql_set_character_set(my, "utf8"); // 这时候就可以插入中文了
// std::string sql = " insert into user (name, age, telphone) values ('tom', 12, '123456789')";
std::string sql = "select * from user";
int n = mysql_query(my, sql.c_str());
if (n == 0)
std::cout << sql << std::endl;
else
{
std::cout << sql << "failed" << std::endl;
return 3;
}
//---------------------------------------------------------------------
MYSQL_RES *res = mysql_store_result(my);
if (nullptr == my)
{
std::cerr << "mysql_store_result error" << std::endl;
return 4;
}
my_ulonglong rows = mysql_num_rows(res);
my_ulonglong fields = mysql_num_fields(res);
std::cout << "行:" << rows << std::endl;
std::cout << "列:" << fields << std::endl;
for (int i = 0; i < rows; i++)
{
MYSQL_ROW row = mysql_fetch_row(res);
for (int j = 0; j < fields; j++)
{
std::cout << row[j] << "\t";
}
std::cout << std::endl;
}
//------------------------------------------------------------------
mysql_free_result(res);
mysql_close(my);
return 0;
}
//结果
syb@VM-8-5-ubuntu:~/mysqltest$ ./mytest
connect success
select * from user
行:3
列:4
1 tom 12 123456789
2 peter 19 2145125324
3 张三 23 83294824
获取列名mysql_fetch_fields
cpp
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);
关于MYSQL_FIELD的结构
里面存储的是关于列的各种信息
cpp
typedef struct MYSQL_FIELD {
char *name; /* Name of column */
char *org_name; /* Original column name, if an alias */
char *table; /* Table of column if column was a field */
char *org_table; /* Org table name, if table was an alias */
char *db; /* Database for table */
char *catalog; /* Catalog for table */
char *def; /* Default value (set by mysql_list_fields) */
unsigned long length; /* Width of column (create length) */
unsigned long max_length; /* Max width for selected set */
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; /* Div flags */
unsigned int decimals; /* Number of decimals in field */
unsigned int charsetnr; /* Character set */
enum enum_field_types type; /* Type of field. See mysql_com.h for types */
void *extension;
} MYSQL_FIELD;
例子:
cpp
#include <iostream>
#include <string>
#include <mysql/mysql.h>
const std::string host = "127.0.0.1";
const std::string user = "connector";
const std::string passwd = "syb020913";
const std::string db = "conn";
const unsigned int port = 3306; // mysqld启动的默认端口是3306,所以连接也用这个
int main()
{
MYSQL *my = mysql_init(nullptr);
if (nullptr == my)
{
std::cerr << "init MySQL error" << std::endl;
return 1;
}
if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
{
std::cerr << "connect MySQL error" << std::endl;
return 2;
}
std::cout << "connect success" << std::endl;
// 建立好链接之后,获取英文没有问题,但是获取中文可能是乱码
// 设置链接的默认字符集是utf8,原始默认是latin1
mysql_set_character_set(my, "utf8"); // 这时候就可以插入中文了
// std::string sql = " insert into user (name, age, telphone) values ('tom', 12, '123456789')";
std::string sql = "select * from user";
int n = mysql_query(my, sql.c_str());
if (n == 0)
std::cout << sql << std::endl;
else
{
std::cout << sql << "failed" << std::endl;
return 3;
}
MYSQL_RES *res = mysql_store_result(my);
if (nullptr == my)
{
std::cerr << "mysql_store_result error" << std::endl;
return 4;
}
my_ulonglong rows = mysql_num_rows(res);
my_ulonglong fields = mysql_num_fields(res);
std::cout << "行:" << rows << std::endl;
std::cout << "列:" << fields << std::endl;
//-------------------------------------------------------------------------
//列属性
MYSQL_FIELD *fields_array = mysql_fetch_fields(res);
for(int i = 0;i<fields;i++)
{
std::cout << fields_array[i].name << "\t";
}
std::cout << std::endl;
//-------------------------------------------------------------------------
//内容
for (int i = 0; i < rows; i++)
{
MYSQL_ROW row = mysql_fetch_row(res);
for (int j = 0; j < fields; j++)
{
std::cout << row[j] << "\t";
}
std::cout << std::endl;
}
mysql_free_result(res);
mysql_close(my);
return 0;
}
//结果
syb@VM-8-5-ubuntu:~/mysqltest$ ./mytest
connect success
select * from user
行:3
列:4
id name age telphone
1 tom 12 123456789
2 peter 19 2145125324
3 张三 23 83294824


