前提准备
要访问MySQL需要下载MySQL,下载时会一起下载MySQL客服端和服务端以及依赖。以C++/C访问MySQL需要用到MySQL提供的API接口,这些API可以在MySQL官网上找到。
yum install myaql-community-server
MySQL句柄
MYSQL* mysql=mysql_init(nullptr);
连接函数
MYSQL *mysql_real_connect(
MYSQL *mysql, // MySQL 连接句柄
const char *host, // 主机名或IP地址
const char *user, // MySQL用户名
const char *passwd, // 密码
const char *db, // 默认数据库
unsigned int port, // 端口号
const char *unix_socket,// Unix域套接字路径
unsigned long client_flag // 客户端标志
);
cpp
#include <iostream>
#include <mysql/mysql.h>
#define HOST "localhost" //或#define HOST "120.0.0.1"
#define USER "root"
#define PASSWORD "123456"
#define DB "conn"
#define PORT 3306
main()
{
//......
mysql = mysql_real_connect(mysql,HOST,USER,PASSWORD,DB,PORT,nullptr,0);
if(mysql==nullptr)
{
std::cout<<"mysql_real_connect fail"<<std::endl;
return 1;
}
//......
return 0;
}
参数解释
mysql:mysql句柄,由mysql_init()初始化的连接句柄指针
host:主机名(如'localhost'或'127.0.0.1')
user:用户名如果为null,表示当前系统登录用户名
passwd:用户密码,如果为null,表示不使用密码
db:要使用的数据库名称,可以为null
port:mysql服务的端口号,为0就是默认端口3306
unix_socker:套接字路径,设置为null,表示默认套接字
client_flag:标志位,很少用到,设置为0
user为null解释
假设你住在一个小区(MySQL服务器 ),单元楼有门禁(MySQL的权限系统)。
方式1:用专属门禁卡(显式指定用户名)
你从钱包里掏出写有 "业主A" 的门禁卡(
user="业主A"
),刷卡进门。结果:
如果卡有效(用户存在且密码正确)→ 门开。
如果卡无效(用户不存在)→ 被保安拦下。
方式2:刷脸(
user=NULL
,用系统用户名)
你没带门禁卡,直接走到摄像头前刷脸。
系统自动识别你的脸,查出你是 "住户B"(当前系统登录用户名),然后尝试用这个身份开门。
结果:
如果小区登记过你的脸(MySQL有用户
住户B
)且无需密码 → 门开。如果没登记或需要密码但你没输入 → 保安拒绝进入。
所以user=null就像刷脸一样,方便但是不安全。
句柄的意义
句柄可以避免直接操作底层,借书的人不会去图书馆仓库找书,句柄隐藏了MySQL内部的复杂实现,如果借书不换,图书馆的书就会越来越少,所以申请的句柄,用完后就需要释放句柄。
- 办借书证 →
mysql_init()
和mysql_real_connect()
你需要先到前台 办一张借书证 (类似创建句柄
MYSQL* conn
)。图书管理员(MySQL服务器 )会登记你的信息(用户名、密码),然后给你一个 借书证编号(句柄的值)。
→ 这个编号不是书本身 ,而是你借书的权限凭证。
- 查目录 →
mysql_query()
你用借书证去查图书目录(SQL查询 ),比如找"所有编程书"(
SELECT * FROM books
)。管理员给你一份临时书单 (结果集句柄
MYSQL_RES* res
),上面列出了书的位置和名字。
- 取书 →
mysql_fetch_row()
你根据书单去书架拿书(获取数据行 )。每本书的内容 (数据)是具体的,但书单(结果集)只是一个指向书的指针。
每次拿一本(
mysql_fetch_row
),直到书架空了(返回NULL
)。
- 还书 →
mysql_free_result()
和mysql_close()
读完书后,你要把书单归还(释放结果集),否则管理员会以为你还在用。
最后退还借书证(关闭连接),否则图书馆会一直保留你的借阅名额(资源泄漏)。
设置客服端字符集
用vscode连接MySQL,这两者的编码方式可能不同,就需要以MySQL的编码方式为准,把vscode的编码同步。
mysql_set_character_set(mysql,"utf8");
选择数据库
刚开始的连接就包含了库的设置,后面出现选择数据库就可以调用这个函数。
mysql_select_db(mysql,"conn");
执行sql语句
mysql是申请的句柄,char的内容会变为字符串输入到mysql中,成功放回0,否则放回非零。
int mysql_query(MYSQL*, const char*)
示例
cpp
std::string insert1 = "insert into stu values(null,'张三',18,187562354)";
n = mysql_query(mysql, insert1.c_str());
if (n != 0)
{
std::cout << "mysql_query fail" << std::endl;
return 1;
}
获取查询结构
在上面的代码中,char内容是select的话,是不会显示表的信息,select不像其它语句增删改,查的信息会保存在一个地方,需要使用API去获取信息。
MYSQL_RES* mysql_store_result(MYSQL*)
函数的返回值为MYSQL_RES* 类型,是一个结构体指针类型,保存了查询结构和相关属性,如下图,每一个char* 都指向表的一个内容,所以要查看表的内容,就需要遍历所有元素,打印出内容。

示例
MYSQL_RES *res = mysql_store_result(mysql);
if (res == nullptr)
{
std::cout << "mysql_store_result fail" << std::endl;
return 1;
}
获取行的个数
int row = mysql_num_rows(res);
获取列的个数
int col = mysql_num_fields(res);
遍历打印
MYSQL_ROW mysql_fetch_row(MYSQL_RES*)
这个函数没调用一次会自动+1,遍历第一行再次调用就到下一行了。
for (int i = 0; i < row; i++)
{
MYSQL_ROW r = mysql_fetch_row(res);
for (int j = 0; j < col; j++)
{
std::cout << r[j] << '/t';
}
std::cout << std::endl;
}
释放申请的资源
void mysql_free_result(MYSQL_RES*)
释放结果集
void mysql_close(MYSQL*);
释放句柄
总代码
cpp
#include <iostream>
#include <mysql/mysql.h>
#define HOST "localhost" // 或#define HOST "120.0.0.1"
#define USER "root"
#define PASSWORD "XyK@71986582"
#define DB "conn"
#define PORT 3306
int main()
{
// 创建MySQL句柄
MYSQL *mysql = mysql_init(nullptr);
// 连接数据库
mysql = mysql_real_connect(mysql, HOST, USER, PASSWORD, DB, PORT, nullptr, 0);
if (mysql == nullptr)
{
std::cout << "mysql_real_connect fail" << std::endl;
return 1;
}
// 设置客户端字符集,与mysqld保持一致。
int n = mysql_set_character_set(mysql, "utf8");
if (n != 0)
{
std::cout << "mysql_setcharacter_set fail" << std::endl;
return 1;
}
// 选择要操作的数据库
// 在做连接时已经选好了现在就不用选,只是考虑到中途需要换其他库的情况。
// n = mysql_select_db(mysql,"conn");
// 准备工作做好了,接下来操作库:
// 执行SQL语句
std::string insert1 = "insert into stu values(null,'张三',18,187562354)";
std::string insert2 = "insert into stu values(null,'李四',18,187562154)";
std::string delete1 = "delete from stu where id=1";
std::string update = "update stu set name='王五' where name = '李四'";
std::string sel = "select * from stu";
n = mysql_query(mysql, sel.c_str());
if (n != 0)
{
std::cout << "mysql_query fail" << std::endl;
return 1;
}
MYSQL_RES *res = mysql_store_result(mysql);
if (res == nullptr)
{
std::cout << "mysql_store_result fail" << std::endl;
return 1;
}
int row = mysql_num_rows(res);
int col = mysql_num_fields(res);
for (int i = 0; i < row; i++)
{
MYSQL_ROW r = mysql_fetch_row(res);
for (int j = 0; j < col; j++)
{
std::cout << r[j] << '\t';
}
std::cout << std::endl;
}
mysql_free_result(res);
mysql_close(mysql);
return 0;
}