C++ 连接 mysql 数据库
C++ 连接 mysql 数据库
分为windows和ubuntu篇,mac等我买下mac pro之后再补充.
Windows
Windows上有一个非常棒的工具Dependencies,当程序无法运行时可以使用它查看哪些动态库没有链接上。
Dependencies
C++ 连接 mysql 数据库,需要手动编译
下载链接如下:
mysql-connector-cpp-github-windows
or
mysql-connector-cpp-github-windows
选择Source Code->Windows (Architecture Independent), ZIP Archive
文件修改
C:\Users\29051\Downloads\mysql-connector-c++-9.5.0-src\mysql-connector-c++-9.5.0-src\jdbc\driver\mysql_util.h
// 第45行
#define UL64(x) x##ui64
// 改为
#define UL64(x) x##ULL
log相关的全部删除
C:\Users\29051\Downloads\mysql-connector-c++-9.5.0-src\mysql-connector-c++-9.5.0-src\cdk\protocol\mysqlx\protocol.cc
/*
大约第116行
Protobuf log handler initialization.
*/
static void log_handler(LogLevel level, const char* filename, int line, const std::string& message);
#ifdef _WIN32
BOOL CALLBACK log_handler_init(PINIT_ONCE, PVOID, PVOID*)
{
SetLogHandler(&log_handler);
return TRUE;
}
#else
static void log_handler_init()
{
SetLogHandler(log_handler);
}
#endif
// 147 行
// Warning can be disabled because the handler is not called, only registered
PUSH_MSVC17_WARNINGS_CDK
EXECUTE_ONCE(&log_handler_once, &log_handler_init);
POP_MSVC17_VARNINGS_CDK
// 292行
static void log_handler(
LogLevel level, const char* /*filename*/, int /*line*/,
const std::string& message
)
{
switch(level)
{
case LOGLEVEL_FATAL:
case LOGLEVEL_ERROR:
/*
With this code the error description is:
MMM: Protobuf error (cdk:NNN)
where MMM is the message and NNN is the protbuf error code.
TODO: Change description to:
Protobuf error: MMM (cdk:NNN)
*/
throw_error(cdkerrc::protobuf_error, message);
case LOGLEVEL_WARNING:
case LOGLEVEL_INFO:
default:
{
// just ignore for now
// TODO: this could be used for logging in the future
}
}
}
删除log_handler相关.
3. 删除顶层cmake
# 大约520行
if(WIN32 AND OPENSSL_LIB_DIR)
# # Note: For simplicity we just copy any DLLs we can find at the given
# # OpenSSL location.
# file(GLOB glob1
# "${OPENSSL_LIB_DIR}/*${CMAKE_SHARED_LIBRARY_SUFFIX}*"
# )
# file(GLOB glob2
# "${OPENSSL_LIB_DIR}/../bin/*${CMAKE_SHARED_LIBRARY_SUFFIX}*"
# )
# if(NOT glob1 AND NOT glob2)
# message(
# "Warning: Not copying OpenSSL DLLs in a POST_BUILD event"
# " of connector target -- they were not found at: ${path}"
# " (OPENSSL_LIB_DIR: ${OPENSSL_LIB_DIR})"
# )
# else()
# add_custom_command(TARGET connector POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E copy
# ${glob1} ${glob2} $<TARGET_FILE_DIR:connector>
# COMMENT "# Copy OpenSSL dependency of connector library."
# )
# endif()
# endif()
编译、安装
使用UCRT64 SHELL编译
cmake .. -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/mysql1 \
-DWITH_MYSQL=/d/SoftWare/MySQL8.4 \
-DWITH_PROTOBUF=system \
-DWITH_LZ4=system \
-DWITH_ZSTD=system \
-DWITH_ZLIB=system \
-DWITH_JDBC=ON
cmake --build . --target install -j$(nproc)
导入动态库
安装目录如下:
D:\SoftWare\msys64\mysql1\lib64
我们一个需要三个动态库
libmysql.dll
libmysqlcppconn-10.dll
libmysqlcppconnx-2.dll
传统api需要如下动态库,session api 不需要,它来自mysql的安装目录D:\SoftWare\MySQL8.4\lib
libmysql.dll
方法1
将三个动态库复制到项目的build目录下

方法2
设置D:\SoftWare\msys64\mysql1\lib64为环境变量,且将libmysql.dll复制到D:\SoftWare\msys64\mysql1\lib64即可。
cmake
cmake_minimum_required(VERSION 3.10.0)
project(mysql_learn01 VERSION 0.1.0 LANGUAGES C CXX)
# ✅ 设置 C++ 标准
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制使用指定标准
set(CMAKE_CXX_EXTENSIONS OFF) # 禁用编译器扩展(使用纯标准)
# 查找源文件
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
"src/*.cpp"
"src/*.c"
)
add_executable(mysql_learn01 main.cpp ${SOURCES})
target_include_directories(${CMAKE_PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/learn01
PRIVATE D:/SoftWare/msys64/mysql1/include/jdbc
PRIVATE D:/SoftWare/msys64/mysql1/include
)
foreach(env $ENV{PATH})
message("env: ${env}")
endforeach()
target_link_libraries(${CMAKE_PROJECT_NAME}
PRIVATE mysqlcppconn # 传统api
PRIVATE mysqlcppconnx # session api
)
include(CTest)
enable_testing()
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
源码
#include <iostream>
#include <cppconn/driver.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <mysqlx/xdevapi.h>
int main(int, char**) {
// sql 语句
const std::string sql = R"(
show databases;
)";
// 传统 api 模式
sql::Driver* driver = get_driver_instance();
const sql::SQLString hostName = "tcp://192.168.31.90";
const sql::SQLString userName = "root";
const sql::SQLString passWord = "root";
sql::Connection* connection = driver->connect(hostName, userName, passWord);
sql::Statement* statement = connection->createStatement();
sql::ResultSet* resultSet = statement->executeQuery(sql);
while (resultSet->next()) {
const auto dbName = resultSet->getString("Database");
std::cout << "dbName: " << dbName << '\n';
}
resultSet->close();
statement->close();
connection->close();
// session 模式
// 创建 Session 连接
mysqlx::Session session(mysqlx::SessionOption::HOST, "192.168.31.90",
mysqlx::SessionOption::PORT, 33060,
mysqlx::SessionOption::USER, "root",
mysqlx::SessionOption::PWD, "root");
mysqlx::SqlResult result = session.sql(sql).execute();
// 使用 RowResult 迭代每一行
mysqlx::Row row;
while ((row = result.fetchOne())) {
std::cout << row[0].get<std::string>() << std::endl;
}
session.close();
}
Mariadb 库
上面官方的mysql-connect/C++,新手如果觉得很复杂可以使用它代替,但无法进行现代化的C++开发。
pacman -S mingw-w64-ucrt-x86_64-libmariadbclient
cmake
cmake_minimum_required(VERSION 3.10.0)
project(mysql_learn01 VERSION 0.1.0 LANGUAGES C CXX)
# ✅ 设置 C++ 标准
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制使用指定标准
set(CMAKE_CXX_EXTENSIONS OFF) # 禁用编译器扩展(使用纯标准)
# 查找源文件
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
"src/*.cpp"
"src/*.c"
)
add_executable(mysql_learn01 main.cpp ${SOURCES})
target_include_directories(${CMAKE_PROJECT_NAME}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/learn01
)
find_package(PkgConfig REQUIRED)
pkg_check_modules(MARIADB REQUIRED libmariadb)
target_include_directories(${PROJECT_NAME} PRIVATE ${MARIADB_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE ${MARIADB_LIBRARIES})
# 遍历一下 include dirs
foreach(includeDir ${MARIADB_INCLUDE_DIRS})
message("includeDir: ${includeDir}")
endforeach()
# 遍历一下 link libraries
foreach(libDir ${MARIADB_LIBRARIES})
message("libDir: ${libDir}")
endforeach()
# 定义字符串变量
set(ZSH "zsh")
message("ZSH: ${ZSH}")
if(NOT "${ZSH}" STREQUAL "")
message("ZSH 不为空")
else()
message("ZSH 为空")
endif()
# 定义布尔变量
set(IS_MAN OFF)
if(IS_MAN)
message("你是男的")
else()
message("你是女的")
endif()
# 变量定义
if(DEFINED MY_VAR)
message(STATUS "MY_VAR is defined: ${MY_VAR}")
else()
message("MY_VAR 未定义")
endif()
# 列表
set(MY_LIST "one;two;three")
foreach(LIST ${MY_LIST})
message("LIST: ${LIST}")
endforeach()
# 定义一个数字
set(AGE "18")
math(EXPR AGE "${AGE} - 1")
message("AGE: ${AGE}")
# 循环从 1 到 100
foreach(i RANGE 1 100)
message("i = ${i}")
endforeach()
include(CTest)
enable_testing()
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
头文件
#ifndef LEARN001_HPP
#define LEARN001_HPP
#include <iostream>
// mysql
#include <mariadb/mysql.h>
namespace learn01 {
void hello();
void getPersonsFromMysql();
}
#endif // LEARN001_HPP
源文件
#include "learn001.hpp"
namespace learn01 {
void hello() { std::cout << "Hello World\n"; }
void getPersonsFromMysql() {
// 还有个全新的session模式
// sql::Driver *driver = get_driver_instance();
// const sql::SQLString hostName = "tcp://localhost:3306";
// const sql::SQLString userName = "root";
// const sql::SQLString passWord = "root";
// sql::Connection *connection = driver->connect(hostName, userName,
// passWord); sql::Statement *statement = connection->createStatement();
// sql::ResultSet *resultSet = statement->executeQuery("show databases;");
// while(resultSet->next()){
// const auto dbName = resultSet->getString("Database");
// std::cout << "dbName: " << dbName << '\n';
// }
// resultSet->close();
// statement->close();
// connection->close();
MYSQL* conn = mysql_init(nullptr);
if (!conn) {
std::cerr << "mysql_init() failed\n";
return;
}
if (!mysql_real_connect(conn, "127.0.0.1", "root", "root", nullptr, 3306,
nullptr, 0)) {
std::cerr << "Connection failed: " << mysql_error(conn) << "\n";
mysql_close(conn);
return;
}
// 执行查询
if (mysql_query(conn, "SHOW DATABASES;")) {
std::cerr << "Query failed: " << mysql_error(conn) << "\n";
mysql_close(conn);
return;
}
MYSQL_RES* res = mysql_store_result(conn);
if (!res) {
std::cerr << "Store result failed: " << mysql_error(conn) << "\n";
mysql_close(conn);
return;
}
MYSQL_ROW row;
std::cout << "Databases:\n";
while ((row = mysql_fetch_row(res)) != nullptr) {
std::cout << " " << row[0] << "\n";
}
mysql_free_result(res);
mysql_close(conn);
}
} // namespace learn01
Linux(Ubuntu)
下载三个deb包即可
libmysqlcppconn10_9.5.0-1ubuntu22.04_amd64.deb # 包含 mysqlcppconn so 库 即 传统 api
libmysqlcppconnx2_9.5.0-1ubuntu22.04_amd64.deb # 包含 mysqlcppconnx so 库 即 session api
libmysqlcppconn-dev_9.5.0-1ubuntu24.04_amd64.deb # 包含头文件
# 安装
sudo dpkg -i libmysqlcppconn10_9.5.0-1ubuntu22.04_amd64.deb
sudo dpkg -i libmysqlcppconnx2_9.5.0-1ubuntu22.04_amd64.deb
sudo dpkg -i libmysqlcppconn-dev_9.5.0-1ubuntu24.04_amd64.deb
cmake
cmake_minimum_required(VERSION 3.10.0)
project(mysql_learn01 VERSION 0.1.0 LANGUAGES C CXX)
# ✅ 设置 C++ 标准
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制使用指定标准
set(CMAKE_CXX_EXTENSIONS OFF) # 禁用编译器扩展(使用纯标准)
# 查找源文件
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
"src/*.cpp"
"src/*.c"
)
add_executable(mysql_learn01 main.cpp ${SOURCES})
target_include_directories(${CMAKE_PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/learn01
PRIVATE /usr/include/mysql-cppconn/jdbc
PRIVATE /usr/include/mysql-cppconn
)
target_link_libraries(${CMAKE_PROJECT_NAME}
PRIVATE mysqlcppconn # 传统api
PRIVATE mysqlcppconnx # session api
)
include(CTest)
enable_testing()
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
源码
#include <cppconn/driver.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <mysqlx/xdevapi.h>
#include <iostream>
int main(int, char**) {
// 传统 api 模式
sql::Driver* driver = get_driver_instance();
const sql::SQLString hostName = "tcp://192.168.31.90";
const sql::SQLString userName = "root";
const sql::SQLString passWord = "root";
sql::Connection* connection = driver->connect(hostName, userName, passWord);
sql::Statement* statement = connection->createStatement();
sql::ResultSet* resultSet = statement->executeQuery("show databases;");
while (resultSet->next()) {
const auto dbName = resultSet->getString("Database");
std::cout << "dbName: " << dbName << '\n';
}
resultSet->close();
statement->close();
connection->close();
// session 模式
// 创建 Session 连接
mysqlx::Session session(mysqlx::SessionOption::HOST, "192.168.31.90",
mysqlx::SessionOption::PORT, 33060,
mysqlx::SessionOption::USER, "root",
mysqlx::SessionOption::PWD, "root");
mysqlx::SqlResult result = session.sql("SHOW DATABASES").execute();
// 使用 RowResult 迭代每一行
mysqlx::Row row;
while ((row = result.fetchOne())) {
std::cout << row[0].get<std::string>() << std::endl;
}
session.close();
}
MacOS
TODO
数据库基本查询
查看有哪些数据库
#include <iostream>
#include <cppconn/driver.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <mysqlx/xdevapi.h>
int main(int, char**) {
// sql 语句
const std::string sql = R"(
show databases;
)";
// 传统 api 模式
sql::Driver* driver = get_driver_instance();
const sql::SQLString hostName = "tcp://192.168.31.90";
const sql::SQLString userName = "root";
const sql::SQLString passWord = "root";
sql::Connection* connection = driver->connect(hostName, userName, passWord);
sql::Statement* statement = connection->createStatement();
sql::ResultSet* resultSet = statement->executeQuery(sql);
while (resultSet->next()) {
const auto dbName = resultSet->getString("Database");
std::cout << "dbName: " << dbName << '\n';
}
resultSet->close();
statement->close();
connection->close();
// session 模式
// 创建 Session 连接
mysqlx::Session session(mysqlx::SessionOption::HOST, "192.168.31.90",
mysqlx::SessionOption::PORT, 33060,
mysqlx::SessionOption::USER, "root",
mysqlx::SessionOption::PWD, "root");
mysqlx::SqlResult result = session.sql(sql).execute();
// 使用 RowResult 迭代每一行
mysqlx::Row row;
while ((row = result.fetchOne())) {
std::cout << row[0].get<std::string>() << std::endl;
}
session.close();
}
增删改查
#include <iostream>
#include <memory>
#include <cppconn/driver.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <mysqlx/xdevapi.h>
struct User {
uint64_t id;
std::string username;
std::string password;
std::string email;
int32_t age;
std::string gender;
explicit User()
: id(0), username(""), password(""), email(""), age(0), gender("男") {
std::cout << "默认构造 p: " << *this << "\n";
}
explicit User(const sql::ResultSet* resultSet)
: id(resultSet->getUInt64("id")),
username(resultSet->getString("username")),
password(resultSet->getString("password")),
email(resultSet->getString("email")),
age(resultSet->getInt("age")),
gender(resultSet->getString("gender")) {
std::cout << "数据库1构造 p: " << *this << "\n";
}
explicit User(const mysqlx::Row& row)
: id(row[0].get<uint64_t>()),
username(row[1].get<std::string>()),
password(row[2].get<std::string>()),
email(row[3].get<std::string>()),
age(row[4].get<int32_t>()),
gender(row[5].get<std::string>()) {
std::cout << "数据库2构造 p: " << *this << "\n";
}
void setId(const uint64_t id) { this->id = id; }
void setUserName(const std::string username) { this->username = username; }
friend std::ostream& operator<<(std::ostream& os, const User& user) {
os << std::format(
"User(id={}, username={}, password={}, email={}, age={}, "
"gender={})",
user.id, user.username, user.password, user.email, user.age,
user.gender);
return os;
}
};
int main(int, char**) {
// sql 语句
const std::string sql1 = R"(
use test;
)";
const std::string sql2 = R"(
select database();
)";
const std::string sql3 = R"(
show tables;
)";
const std::string sql4 = R"(
desc t_user;
)";
const std::string sql5 = R"(
show create table t_user;
)";
const std::string sql6 = R"(
select *
from information_schema.columns
where table_schema = 'test'
and table_name = 't_user';
)";
// 增
const std::string sql7 = R"(
insert into t_user (username, password, email, age, gender)
values ('tom', '123456', 'tom@qq.com', 20, '男'), ('tom1', '1234567', 'tom1@qq.com', 21, '男1');
)";
const std::string sql8 = R"(
insert into t_user (username, password, email, age, gender)
values (?, ?, ?, ?, ?);
)";
// 批量增加
// 删
// 改
// 查
const std::string sql11 = R"(
select * from t_user;
)";
// 传统 api 模式
sql::Driver* driver = get_driver_instance();
const sql::SQLString hostName = "tcp://192.168.31.90";
const sql::SQLString userName = "root";
const sql::SQLString passWord = "root";
sql::Connection* connection = driver->connect(hostName, userName, passWord);
sql::Statement* statement = connection->createStatement();
{
const auto result =
statement->execute(sql1); // execute返回结果代表是否有
// ResultSet,没有抛异常就证明执行成功
std::cout << std::format("sql1执行是否成功: {}", result) << "\n";
}
sql::ResultSet* resultSet = statement->executeQuery(sql2);
while (resultSet->next()) {
const auto dbName = resultSet->getString(1); // 获取第一列
std::cout << "dbName: " << dbName << '\n';
}
resultSet = statement->executeQuery(sql3);
while (resultSet->next()) {
const auto tableName = resultSet->getString(1); // 获取第一列
std::cout << "tableName: " << tableName << '\n';
}
resultSet = statement->executeQuery(sql4);
std::cout << "查看表结构\n";
{
// 查看有多少行,多少列,表头信息
const auto columnCount = resultSet->getMetaData()->getColumnCount();
std::cout << "columnCount: " << columnCount << "\n";
}
while (resultSet->next()) {
const auto columnName = resultSet->getMetaData()->getColumnName(1);
std::cout << "columnName: " << columnName << "\n";
resultSet->getMetaData()->getTableName(1);
const auto field = resultSet->getString(1); // 获取第一列
const auto type = resultSet->getString(2); // 获取第一列
const auto nullable = resultSet->getString(3); // 获取第一列
const auto key = resultSet->getString(4); // 获取第一列
const auto defaultValue = resultSet->getString(5); // 获取第一列
const auto tableName6 = resultSet->getString(6); // 获取第一列
std::cout << std::format(
"field: {}, type: {}, nullable: {}, key: {}, defaultValue: {}, "
"tableName6: {}\n",
field.asStdString(), type.asStdString(), nullable.asStdString(),
key.asStdString(), defaultValue.asStdString(),
tableName6.asStdString());
}
// 插入
// auto affectRows = statement->executeUpdate(sql7);
// if(affectRows > 0){
// std::cout << "插入成功\n";
// }
// 安全插入 + 事务
connection->setAutoCommit(false);
try{
// sql::PreparedStatement* prepareStatement = connection->prepareStatement(sql8);
// const auto prepareStatement = std::make_unique<sql::PreparedStatement>(connection->prepareStatement(sql8)); // 没有构造函数的话不能这样调用
const auto prepareStatement = std::unique_ptr<sql::PreparedStatement>(connection->prepareStatement(sql8));
prepareStatement->setString(1, "lisa");
prepareStatement->setString(2, "888888");
prepareStatement->setString(3, "lisa@qq.com");
prepareStatement->setInt(4, 22);
prepareStatement->setString(5, "女");
const auto rows = prepareStatement->executeUpdate();
resultSet = statement->executeQuery("select last_insert_id();");
if (resultSet->next()) {
std::cout << "插入记录 ID = " << resultSet->getUInt64(1) << std::endl;
}
if (rows > 0) {
std::cout << "插入成功, 是否有更多结果集: " << prepareStatement->getMoreResults() << "\n";
}
throw std::runtime_error("运行时异常1");
connection->commit();
} catch (sql::SQLException& e) {
// 回滚事务
connection->rollback();
std::cout << "事务回滚, 原因: " << e.what() << std::endl;
}
// 查询
resultSet = statement->executeQuery(sql11);
{
// 查看有多少行,多少列,表头信息
const auto columnCount = resultSet->getMetaData()->getColumnCount();
std::cout << "columnCount: " << columnCount << "\n";
while (resultSet->next()) {
User user(resultSet);
std::cout << user << "\n";
}
}
resultSet->close();
statement->close();
connection->close();
delete resultSet;
delete statement;
delete connection;
std::cout << "============================================================="
"====\n";
// session 模式
// 创建 Session 连接
mysqlx::Session session(mysqlx::SessionOption::HOST, "192.168.31.90",
mysqlx::SessionOption::PORT, 33060,
mysqlx::SessionOption::USER, "root",
mysqlx::SessionOption::PWD, "root");
mysqlx::SqlResult result = session.sql(sql1).execute();
if (result.count() > 0) {
std::cout << "执行成功\n";
}
result = session.sql(sql2).execute();
// 使用 RowResult 迭代每一行
mysqlx::Row row;
while ((row = result.fetchOne())) {
std::cout << row[0].get<std::string>() << std::endl;
}
result = session.sql(sql3).execute();
while ((row = result.fetchOne())) {
std::cout << row[0].get<std::string>() << std::endl;
}
std::cout << "查看表结构: \n";
result = session.sql(sql4).execute();
while ((row = result.fetchOne())) {
const auto field = row[0].get<std::string>(); // 获取第一列
const auto type = row[1].get<std::string>(); // 获取第一列
const auto nullable = row[2].get<std::string>(); // 获取第一列
const auto key = row[3].get<std::string>(); // 获取第一列
const auto defaultValue =
row[4].isNull() ? "" : row[4].get<std::string>(); // 获取第一列
const auto tableName6 = row[5].get<std::string>(); // 获取第一列
std::cout << std::format(
"field: {}, type: {}, nullable: {}, key: {}, defaultValue: {}, "
"tableName6: {}\n",
field, type, nullable, key, defaultValue, tableName6);
}
// 插入
// std::cout << "插入:\n";
// result = session.sql(sql7).execute();
// if(result.getAffectedItemsCount() > 0){
// std::cout << "插入成功\n";
// }
// 插入2
session.startTransaction();
try {
result = session.sql(sql8)
.bind("lisa", "888888", "lisa@qq.com", 22, "女")
.execute();
if(result.getAffectedItemsCount() > 0){
std::cout << "插入成功, 主键id为: " << result.getAutoIncrementValue() << "\n";
}
throw std::runtime_error("运行时异常1");
session.commit();
} catch (const std::exception& e) {
std::cerr << "session异常: " << e.what() << '\n';
}
std::cout << "查询:\n";
result = session.sql(sql11).execute();
while ((row = result.fetchOne())) {
User user(row);
std::cout << user << "\n";
}
// 事务
session.close();
}
剩余修改、和删除留给读者自己尝试,有什么疑问可以问我。
有什么不足还请各位大佬指出!

浙公网安备 33010602011771号