Connector C++ 连接 MySQL 数据库之增删改查
在 vcpkg 中折腾了 mysql-connector-cpp 8.0 很久,一直连接不上远程数据库,后面查官方文档,mysql-connector-cpp 8.0 好像只支持 MySQL 8.0 以上的数据库,本来想把远程服务器上的 MySQL 升级到 MySQL 8.0,后面发现测试服务器的配置有点拉跨,架不住 MySQL 8.0,但是 vcpkg 中又没有 mysql-connector-cpp 的其他版本,那就只能自己找一个低版本的 mysql-connector-cpp,然后手动进行配置了...
我的实验 MySQL 版本为 mysql 5.5,Connector/C++ 为 9.0.0(为什么 vcpkg 里面的 mysql-connector-cpp 8.0 不行啊,老是配置出错,后面再回来看看...)。
回来填坑:原来是没找到正确的使用姿势,可以参考下面文章:https://holdyounger.github.io/C_OpenSource/MySQL/mysql-connnector-8.0编译说明/#:~:text=使用 JDBC 连接
一、配置 Connector/C++ 编译环境
step 1 下载 Connector/C++ 9.0.0
通过下面链接下载:
https://dev.mysql.com/downloads/connector/cpp/
这是 MySQL 官方专门提供给 C++ 开发的库文件,分为 Release 和 Debug 版本,我们选择 Release 版本进行实验,当然,我们的编译器也要记得切换到 Release 版本,下载红框里面的文件进行解压,放置到程序目录:
我们来看一下解压后的文件夹,include
为头文件夹,lib64
为库文件:
step 2 配置调试环境
为什么要配置调试环境呢?是因为我们生成的程序需要依赖一些 .dll
动态链接库,而这个动态链接库没有放在我们的程序根目录,所以程序在调试的时候是找不到这些动态链接库的,所以调试的时候就会出现如下的错误:
所以我们来设置调试环境,右键项目 -> 属性 -> 配置属性 -> 调试 -> 环境,填入如下路径:
PATH=C:\Users\Administrator\Desktop\其他\演示代码\6 Connector C++ 连接 MySQL 数据库之增删改查\demo\mysql-connector-c++-9.0.0-winx64\lib64;
注意最后的 ;
一定要加上,否则会出问题,很多朋友配置环境的时候可能习惯最后不加分号。
在属性页配置环境的时候,一定要记得配置调成 Release,这是个容易忽略的低级 bug。
step 3 引入包含目录
我们需要在配置也中设置库所在的头文件路径,右键项目 -> 属性 -> 配置属性 -> C/C++ -> 常规 -> 附加包含目录,设置如下:
C:\Users\Administrator\Desktop\其他\演示代码\6 Connector C++ 连接 MySQL 数据库之增删改查\demo\mysql-connector-c++-9.0.0-winx64\include;
当然如果我们的库文件和项目文件一起移动的话,我们最好把路径设置成相对路径,比如我们的工作目录为:
C:\Users\Administrator\Desktop\其他\演示代码\6 Connector C++ 连接 MySQL 数据库之增删改查\demo\console_database
那么包含目录,我们可以设置成如下的相对路径:
..\mysql-connector-c++-9.0.0-winx64\lib64;
其他的路径设置也是同理,当然如果我们不同的项目需要重复的引用这些库文件,那么我们可以把库文件统一放置到 D 盘的一个文件夹中,然后在路径设置中填上绝对路径,像 vcpkg 一样,对库文件进行统一管理,就不需要把库文件内置到单独的项目中了。
step 4 引入库目录
引入了头文件的包含目录后,我们还需要告诉编译器库目录在哪里,右键项目 -> 属性 -> 配置属性 -> 链接器 -> 常规 -> 附加库目录,设置如下:
C:\Users\Administrator\Desktop\其他\演示代码\6 Connector C++ 连接 MySQL 数据库之增删改查\demo\mysql-connector-c++-9.0.0-winx64\lib64\vs14;
step 5 指定依赖的库文件
最后我们还需要高速编译器,我们项目中需要用到哪些库文件,右键项目 -> 属性 -> 配置属性 -> 链接器 -> 输入 -> 附加依赖项,在最后面追加 mysqlcppconn.lib;
:
kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);mysqlcppconn.lib;
二、MySQL 数据库基本操作
在用代码连接 MySQL 数据库之前,我们需要了解一下常用的数据库语法,虽然每种数据库的语法都会有自己的特点,但是大部分数据库的操作都是互通的,我们可以通过下面的网址进行数据库基本操作的学习:
https://www.runoob.com/sql/sql-tutorial.html
三、Connector C++ 连接 MySQL 数据库之增删改查
在做完所有的前置工作后,我们就可以进入今天的主题了。
step 1 加载驱动、建立连接并设置默认数据库
// 加载驱动
sql::Driver* driver = sql::mysql::get_driver_instance();
// 建立连接
std::unique_ptr<sql::Connection> conn(driver->connect("tcp://host:3306", "admin", "123456"));
// 设置默认数据库(也可以在 conn->createStatement() 返回 sql::Statement 后设置)
conn->setSchema("database1");
建立连接时,如果是连接本地数据库 host
可以填上 localhost
或 127.0.0.1
,建立完成后,我们需要设置一下默认数据库是哪个,因为一个 MySQL 可能会架设多个数据库,而我们在建立连接的时候需要填入我们需要连接的数据库相应的账号和密码。
step 2 创建表
SQL 语法创建表:
create table if not exists websites (id int auto_increment primary key, name varchar(255), url text, country varchar(255));
MySQL 数据库对 SQL 语法关键字的大小写不敏感,所以可以用小写,SQL 语句中涉及到字符串用单引号或者双引号都可以,若涉及到特殊字符,可以用
R"()"
来表示原始字符串(写在括号中间),即不对字符串做任何处理(主要是\
、'
和"
不生效)。
C++ 对应操作:
// 创建表
std::unique_ptr<sql::Statement> createStatement(conn->createStatement());
//createStatement->execute("use database1"); // 设置默认数据库
createStatement->execute("create table if not exists websites ("
"id int auto_increment primary key, "
"name varchar(255), "
"url text, "
"country varchar(255))");
step 3 插入数据
SQL 语法插入数据:
insert into websites values ("Google", "https://www.google.cm/", "USA");
insert into websites values ("taobao", "https://www.taobao.com/", "USA");
C++ 对应操作:
// 插入数据
std::unique_ptr<sql::PreparedStatement>
insertStatement(conn->prepareStatement("insert into websites (name, url, country) values (?, ?, ?)"));
insertStatement->setString(1, "Google");
insertStatement->setString(2, "https://www.google.cm/");
insertStatement->setString(3, "USA");
insertStatement->execute();
insertStatement->setString(1, "taobao");
insertStatement->setString(2, "https://www.taobao.com/");
insertStatement->setString(3, "USA");
insertStatement->execute();
//conn->prepareStatement(R"(insert into websites values ("taobao", "https://www.taobao.com/", "USA"))")->execute();
step 4 更新数据
SQL 语法更新数据:
update websites set country="CN" where name="taobao";
C++ 对应操作:
// 更新数据
std::unique_ptr<sql::PreparedStatement>
updateState(conn->prepareStatement("update websites set country=? where name=?"));
updateState->setString(1, "CN");
updateState->setString(2, "taobao");
updateState->execute();
在更新数据的时候,一定千万要注意,后面要加上
where
关键字来限定需要更新的某条或多条符合条件的数据,如果不加限定条件,会更新所有数据的相应列,所以在使用update
操作的时候一定要谨慎。
step 5 查询数据
SQL 语法查询数据:
select * from websites;
C++ 对应操作:
// 查询数据
std::unique_ptr<sql::Statement> selectStatement(conn->createStatement());
std::unique_ptr<sql::ResultSet> res(selectStatement->executeQuery("select * from websites"));
while (res->next())
{
std::cout << "id: " << res->getInt("id") << ", "
<< "name: " << res->getString("name") << ", "
<< "url: " << res->getString("url") << ", "
<< "country: " << res->getString("country") << std::endl;
}
当然我们也可以在后面加上关键字
where
来限定条件查询。
查询结果如下:
step 5 删除数据
SQL 语法删除数据:
delete from websites where name="Google";
C++ 对应操作:
// 删除数据
std::unique_ptr<sql::PreparedStatement>
deleteStatement(conn->prepareStatement("delete from websites where name=?"));
deleteStatement->setString(1, "Google");
deleteStatement->execute();
step 6 删除表
SQL 语法删除表:
drop table if exists websites;
C++ 对应操作:
// 删除表
createStatement->execute("drop table if exists websites");
四、打包成一个可执行文件
我们在编写代码的时候引入了库文件,而且调试运行的时候也需要依赖动态链接库,那么我们如果想发布软件还要带上相应的动态链接库的话,那是不是感觉是一件很麻烦的事情,所以我们需要将所有的文件打包成一个可执行文件,这样它就可以随时随地在其他的设备上运行了。
很多朋友可能会用静态库的方式进行编译,使得程序能够以一个单一的可执行文件呈现在其他设备上,但是各种类型的静态库配置要求不一,过于麻烦,这里推荐一个工具:Enigma Virtual Box
,该工具有以下几个优点:
- Enigma 虚拟文件打包系统不会释放临时文件到您的计算机,也不会将打包文件释放至硬盘
- Enigma 虚拟文件打包系统支持 x86 (32位) 和 x64 (64位) 文件,打包后程序能运行在所有的 Windows 操作系统中
- Enigma 虚拟文件打包系统完全是免费的应用程序,您不必支付任何费用就可以使用它!
- Enigma 虚拟文件打包系统支持各种类型的文件进行虚拟打包
- Enigma 虚拟文件打包系统支持文件的压缩,从而大幅减少生成文件的体积
好东西,从此妈妈再也不用担心我需要编译各种静态库了...
接下来进行打包:
step 1
首先,我们右键项目 -> 配置属性 -> 高级 -> MFC 的使用,设置为 在静态库中使用 MFC
,然后 右键项目 -> 配置属性 -> C/C++ -> 代码生成 -> 运行库,设置为 多线程(/MT)
。
关于为什么要进行这种设置,可以参考这篇文章:
https://blog.csdn.net/Zander0/article/details/116400481#:~:text=目的:Visual
step 2
用 Dependency Walker
工具对可执行文件的依赖库进行查看,将依赖库全部复制到可执行文件的当前文件夹(其实也可以直接把可执行文件拖到一个单独的文件夹点击执行,它会提示缺少哪些动态链接库),然后用 Enigma Virtual Box
工具进行打包