C++ 连接 mysql 数据库

C++ 连接 mysql 数据库

分为windowsubuntu篇,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

文件修改

  1. 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
  1. 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目录下
image

方法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();
}

剩余修改、和删除留给读者自己尝试,有什么疑问可以问我。

有什么不足还请各位大佬指出!

posted @ 2025-11-12 23:01  爱情丶眨眼而去  阅读(6)  评论(0)    收藏  举报