目录
一、准备工作
二、数据表操作
(一)初始化数据库
(二)连接数据库
(三)设置字符集
(四)操作数据表
1、插入数据
2、删除数据
3、更新数据
4、查询数据
一、准备工作
在之前的文章中都是使用 MySQL 客户端以命令行的形式进行数据库操作,但在实际开发中是以语言级别的形式对数据库进行操作。
首先需要创建一个用户以供操作,用户管理详见:【MySQL】视图与用户管理-CSDN博客
其次还需要准备一个测试表:
mysql> create table person(-> id int primary key auto_increment,-> name varchar(20) not null,-> age int not null,-> telephone varchar(20) unique);
Query OK, 0 rows affected (0.02 sec)mysql> insert into person values(1,'张三',18,'123456'), (2,'李四',20,'123789');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0mysql> select * from person;
+----+--------+-----+-----------+
| id | name | age | telephone |
+----+--------+-----+-----------+
| 1 | 张三 | 18 | 123456 |
| 2 | 李四 | 20 | 123789 |
+----+--------+-----+-----------+
2 rows in set (0.00 sec)
接下来需要配置环境,只要正常下载了 MySQL,它会自动把相关的库也会给配置好,在使用时需要配置好项目的环境以及包含好相应的头文件即可。以下是用于验证代码环境是否配置成功:
# 下载并安装 MySQL 仓库配置
sudo dnf install https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm# 更新仓库缓存
sudo dnf update# 安装 MySQL 开发包(包含头文件和链接库)
sudo dnf install mysql-devel
# 若GBK报错
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
sudo dnf clean all
# 若无效
sudo dnf install mysql-community-devel --nogpgcheck# 查看头文件路径(关键用于 C 编译)
ls /usr/include/mysql //若输出包含 mysql.h 等头文件,则安装成功
当配置好坏境以后,我们就可以使用 MySQL 提供的 API 进行编程了。
#include <iostream>
#include <mysql.h>
using namespace std;
int main()
{printf("mysql client Version: %s\n", mysql_get_client_info());return 0;
}
在编译连接时需要指明 MySQL 头文件以及库文件,以下是makefile文件:
mysql:mysql.cppg++ -o $@ $^ -std=c++11 -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient
.PHONY:clean
clean:rm -rf mysql
二、数据表操作
(一)初始化数据库
//初始化数据库
MYSQL *mysql_init(MYSQL *mysql);
作用:初始化数据库,连接数据库前的必要条件;
参数:若传入NULL,则会新建并初始化一个MySQL对象;
若传入已有的MySQL指针,则会重置该指向的对象;
返回值:成功返回初始化后的对象,失败返回NULL。
(二)连接数据库
想对数据库进行操作,必须先进行初始化,之后再需要连接数据库。
//连接数据库
MYSQL *mysql_real_connect(MYSQL *mysql, // 已初始化的 MYSQL 结构体指针const char *host, // 服务器主机名或 IP 地址const char *user, // 登录用户名const char *passwd, // 登录密码const char *db, // 默认数据库名unsigned int port, // TCP/IP 端口号(0 表示默认 3306)const char *unix_socket,// Unix 套接字路径(NULL 表示不使用)unsigned long client_flag //客户端标志位(通常为 0)
);
作用:连接数据库;
参数:各个字段意义已在代码中注释;
返回值:成功返回传入的 MySQL 指针,失败返回NULL。
案例:
#include <iostream>
#include <string>
#include <mysql.h>
using namespace std;
const string host = "127.0.0.1";
const string user = "X";
const string passwd = "Mht1412.";
const string db_name = "test";int main()
{MYSQL *mysql = mysql_init(nullptr);if (!mysql){cerr << "初始化失败" << endl;return 1;}if (!mysql_real_connect(mysql, host.c_str(), user.c_str(), passwd.c_str(), db_name.c_str(), 3306, nullptr, 0)){cerr << "数据库连接失败" << endl;return 2;}cout << "数据库连接成功" << endl;mysql_close(mysql); // 关闭MySQLreturn 0;
}
(三)设置字符集
连接数据库成功后,已经可以正常对表进行操作,但是获取中文会是乱码。这是因为原始默认的字符集时 latin1, 需要设置为 utf8。
//设置字符集
mysql_set_character_set(myfd, "utf8");
(四)操作数据表
对数据表进行操作使用的是同一个接口,只是传入不同的参数从而达到不同的效果:
int mysql_query(MYSQL *mysql, const char *q);
作用:操作数据表;
参数:指针mysql 为初始化生成的mysql指针,也就是数据库句柄;
q 为传入的 MySQL 语句。
返回值:成功返回0,失败返回非0。
1、插入数据
#include <iostream>
#include <string>
#include <mysql.h>
using namespace std;
const string host = "127.0.0.1";
const string user = "X";
const string passwd = "Mht1412.";
const string db_name = "test";int main()
{MYSQL *mysql = mysql_init(nullptr);if (!mysql){cerr << "初始化失败" << endl;return 1;}if (!mysql_real_connect(mysql, host.c_str(), user.c_str(), passwd.c_str(), db_name.c_str(), 3306, nullptr, 0)){cerr << "数据库连接失败" << endl;return 2;}cout << "数据库连接成功" << endl;string sql = "insert into person values (3, '王五', 19, 456789)";if (mysql_query(mysql, sql.c_str())){cerr << "数据库操作失败" << endl;return 3;}cout << "数据库操作成功" << endl;mysql_close(mysql); // 关闭MySQLreturn 0;
}
运行结果:
2、删除数据
#include <iostream>
#include <string>
#include <mysql.h>
using namespace std;
const string host = "127.0.0.1";
const string user = "X";
const string passwd = "Mht1412.";
const string db_name = "test";int main()
{MYSQL *mysql = mysql_init(nullptr);if (!mysql){cerr << "初始化失败" << endl;return 1;}if (!mysql_real_connect(mysql, host.c_str(), user.c_str(), passwd.c_str(), db_name.c_str(), 3306, nullptr, 0)){cerr << "数据库连接失败" << endl;return 2;}cout << "数据库连接成功" << endl;string sql = "delete from person where id = 3";if (mysql_query(mysql, sql.c_str())){cerr << "数据库操作失败" << endl;return 3;}cout << "数据库操作成功" << endl;mysql_close(mysql); // 关闭MySQLreturn 0;
}
运行结果:
3、更新数据
#include <iostream>
#include <string>
#include <mysql.h>
using namespace std;
const string host = "127.0.0.1";
const string user = "X";
const string passwd = "Mht1412.";
const string db_name = "test";int main()
{MYSQL *mysql = mysql_init(nullptr);if (!mysql){cerr << "初始化失败" << endl;return 1;}if (!mysql_real_connect(mysql, host.c_str(), user.c_str(), passwd.c_str(), db_name.c_str(), 3306, nullptr, 0)){cerr << "数据库连接失败" << endl;return 2;}cout << "数据库连接成功" << endl;string sql = "update person set name='王五' where name='张三'";if (mysql_query(mysql, sql.c_str())){cerr << "数据库操作失败" << endl;return 3;}cout << "数据库操作成功" << endl;mysql_close(mysql); // 关闭MySQLreturn 0;
}
运行结果:
4、查询数据
不同于插入、删除与更新操作,查询数据执行成功后是需要显示数据的,因此需要获取查询结果。
//获取查询结果
MYSQL_RES *mysql_store_result(MYSQL *mysql);
//获取查询结果列名
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);、
//获取查询结果行数
unsigned int mysql_num_rows(MYSQL_RES *res);
//获取查询结果列数
unsigned int mysql_num_fields(MYSQL_RES *res);
//获取结果内容
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
//释放存储结果
void mysql_free_result((MYSQL_RES *result);
其中 MYSQL_RES 结构体在使用层面上可以简单理解为二维数组, MYSQL_ROW 是记录数据表中一行的数据,可以简单理解为迭代器在整个返回的数据内容中进行遍历。
#include <iostream>
#include <string>
#include <mysql.h>
using namespace std;
const string host = "127.0.0.1";
const string user = "X";
const string passwd = "Mht1412.";
const string db_name = "test";int main()
{MYSQL *mysql = mysql_init(nullptr);if (!mysql){cerr << "初始化失败" << endl;return 1;}if (!mysql_real_connect(mysql, host.c_str(), user.c_str(), passwd.c_str(), db_name.c_str(), 3306, nullptr, 0)){cerr << "数据库连接失败" << endl;return 2;}cout << "数据库连接成功" << endl;string sql = "select * from person";if (mysql_query(mysql, sql.c_str())){cerr << "数据库操作失败" << endl;return 3;}cout << "数据库操作成功" << endl;// 获取查询结果MYSQL_RES *res = mysql_store_result(mysql);// 获取查询结果行列数unsigned int rows = mysql_num_rows(res);unsigned int fields = mysql_num_fields(res);// 获取查询结果列名MYSQL_FIELD *fifld = mysql_fetch_fields(res);for (int i = 0; i < fields; ++i){cout << fifld[i].name << "\t";}cout << endl;for (int i = 0; i < rows; ++i){// 依次获取查询结果中行信息MYSQL_ROW row = mysql_fetch_row(res);for (int j = 0; j < fields; ++j){cout << row[j] << "\t";}cout << endl;}// 释放查询结果mysql_free_result(res);mysql_close(mysql); // 关闭MySQLreturn 0;
}
运行结果: