【C/C++ 数据库编程】从零开始:使用 C/C++ 连接与操作 MySQL 数据库
摘要
在现代应用开发中,数据库交互是核心环节。MySQL 作为一款流行的开源关系型数据库,C/C++ 语言提供了强大的库来实现与其的高效连接与数据操作。本文将从环境搭建入手,详细介绍如何在 C 和 C++ 中链接 MySQL,并通过代码示例演示查询、插入、更新和删除等常见操作。同时,本文也将强调安全性与最佳实践,帮助开发者构建健壮的数据库应用。
一、准备工作:安装与配置
在编写代码前,需要确保你的系统已安装 MySQL 服务器和相应的 C/C++ 开发库。
1.1 安装 MySQL 服务器
Windows
- 访问 MySQL 官方网站 下载
MySQL Installer。 - 运行安装程序,推荐选择
Developer Default或Server Only。 - 按提示完成安装,并设置
root用户密码。 - 建议将 MySQL 服务设置为
Automatic(开机自启)。
macOS (使用 Homebrew)
bash
# 安装 Homebrew (如果未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 安装 MySQL
brew install mysql
# 启动 MySQL 服务
brew services start mysql
# 运行安全脚本进行初始化
mysql_secure_installation
Linux (以 Ubuntu/Debian 为例)
bash
# 更新软件包列表
sudo apt update
# 安装 MySQL 服务器
sudo apt install mysql-server
# 启动并设置开机自启
sudo systemctl start mysql
sudo systemctl enable mysql
# 运行安全脚本进行初始化
sudo mysql_secure_installation
验证安装:在终端或命令提示符中输入 mysql --version,若能看到版本信息则表示安装成功。
1.2 安装 C/C++ 开发库
这是编译连接 MySQL 代码的关键。
C 语言开发库 (libmysqlclient)
- Ubuntu/Debian:
bash
sudo apt-get install libmysqlclient-dev - CentOS/RHEL:
bash
sudo yum install mysql-devel - macOS (Homebrew):
brew install mysql命令已包含开发库。 - Windows: 在安装 MySQL Server 时,勾选 "C Connector" 即可。
C++ 开发库 (MySQL Connector/C++)
C++ 的连接器需要单独安装。
- Ubuntu/Debian:
bash
sudo apt-get install libmysqlcppconn-dev - macOS (Homebrew):
bash
brew install mysql-connector-c++ - Windows: 从 MySQL 官网 下载预编译包,并在项目中配置头文件和库文件路径。
1.3 解决密码验证插件问题 (重要)
新版 MySQL 默认使用 caching_sha2_password 插件,这可能导致部分旧版 C/C++ 客户端连接失败。推荐为开发用户设置兼容性更好的 mysql_native_password。
sql
-- 登录 MySQL
mysql -u root -p
-- 修改用户的密码验证插件
ALTER USER 'your_username'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';
FLUSH PRIVILEGES;
请将 your_username 和 your_password 替换为你的实际信息。
二、使用 C 语言链接 MySQL 数据库
C 语言通过 libmysqlclient 库与 MySQL 交互,这是最基础、性能最高的方式。
2.1 核心步骤
- 引入头文件:
#include <mysql/mysql.h> - 初始化连接句柄:
mysql_init() - 建立连接:
mysql_real_connect() - 执行 SQL 语句:
mysql_query() - 处理结果集:
mysql_store_result()/mysql_fetch_row() - 释放资源:
mysql_free_result() - 关闭连接:
mysql_close()
2.2 完整代码示例 (main.c)
c
#include <mysql/mysql.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 数据库配置信息,请替换为你自己的
#define DB_HOST "localhost"
#define DB_USER "your_username"
#define DB_PASS "your_password"
#define DB_NAME "your_database"
void print_error_and_exit(MYSQL *conn, const char *message) {
fprintf(stderr, "%s: %s\n", message, mysql_error(conn));
mysql_close(conn);
exit(EXIT_FAILURE);
}
int main() {
MYSQL *conn;
MYSQL_RES *result;
MYSQL_ROW row;
// 1. 初始化 MySQL 连接对象
conn = mysql_init(NULL);
if (conn == NULL) {
fprintf(stderr, "mysql_init() failed\n");
return EXIT_FAILURE;
}
// 2. 建立与 MySQL 数据库的连接
if (mysql_real_connect(conn, DB_HOST, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0) == NULL) {
print_error_and_exit(conn, "mysql_real_connect() failed");
}
printf("C: 成功连接到 MySQL 数据库!\n");
// 3. 执行查询操作 (SELECT)
const char *select_query = "SELECT * FROM your_table";
if (mysql_query(conn, select_query)) {
print_error_and_exit(conn, "SELECT query failed");
}
result = mysql_store_result(conn);
if (result == NULL) {
print_error_and_exit(conn, "mysql_store_result() failed");
}
int num_fields = mysql_num_fields(result);
printf("\n--- 查询结果 ---\n");
while ((row = mysql_fetch_row(result))) {
for (int i = 0; i < num_fields; i++) {
printf("%s\t", row[i] ? row[i] : "NULL");
}
printf("\n");
}
mysql_free_result(result); // 释放结果集
// 4. 执行插入操作 (INSERT)
char insert_query[256];
const char *value1 = "data1";
const char *value2 = "data2";
snprintf(insert_query, sizeof(insert_query),
"INSERT INTO your_table (column1, column2) VALUES ('%s', '%s')", value1, value2);
if (mysql_query(conn, insert_query)) {
print_error_and_exit(conn, "INSERT query failed");
}
printf("\nC: 成功插入 %lu 行数据。\n", (unsigned long)mysql_affected_rows(conn));
// 5. 关闭连接
mysql_close(conn);
printf("\nC: 数据库连接已关闭。\n");
return EXIT_SUCCESS;
}
注意: 上述代码中的
your_table,column1,column2等需要替换为你数据库中的实际表名和列名。
2.3 编译与运行
打开终端,使用以下命令编译 C 代码:
bash
gcc main.c -o main_c $(mysql_config --cflags --libs)
运行程序:
bash
./main_c
三、使用 C++ 语言链接 MySQL 数据库
C++ 推荐使用官方的 MySQL Connector/C++,它提供了面向对象的 API,更符合 C++ 的编程习惯,并且通过预处理语句能有效防止 SQL 注入。
3.1 核心步骤
- 引入头文件:
#include <cppconn/...> - 获取驱动实例:
sql::mysql::get_driver_instance() - 建立连接:
driver->connect() - 创建并执行语句:
createStatement()或prepareStatement() - 处理结果集:
ResultSet - 释放资源: 使用
delete(或智能指针) - 异常处理: 使用
try...catch捕获sql::SQLException
3.2 完整代码示例 (main.cpp)
cpp
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <iostream>
// 数据库配置信息,请替换为你自己的
const std::string DB_HOST = "tcp://127.0.0.1:3306";
const std::string DB_USER = "your_username";
const std::string DB_PASS = "your_password";
const std::string DB_NAME = "your_database";
int main() {
sql::Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
sql::PreparedStatement *prep_stmt;
try {
// 1. 获取 MySQL 驱动实例
driver = sql::mysql::get_driver_instance();
// 2. 建立连接
con = driver->connect(DB_HOST, DB_USER, DB_PASS);
con->setSchema(DB_NAME);
std::cout << "C++: 成功连接到 MySQL 数据库!" << std::endl;
// 3. 执行查询操作 (SELECT)
stmt = con->createStatement();
res = stmt->executeQuery("SELECT * FROM your_table");
std::cout << "\n--- 查询结果 ---" << std::endl;
while (res->next()) {
// 假设表中有两列,可以使用列名或索引访问
std::cout << "ID: " << res->getInt("id")
<< ", Column1: " << res->getString("column1")
<< ", Column2: " << res->getString("column2") << std::endl;
}
delete res;
delete stmt;
// 4. 执行插入操作 (INSERT) 使用预处理语句,安全!
prep_stmt = con->prepareStatement("INSERT INTO your_table (column1, column2) VALUES (?, ?)");
prep_stmt->setString(1, "cpp_value1");
prep_stmt->setString(2, "cpp_value2");
prep_stmt->executeUpdate();
std::cout << "\nC++: 成功插入数据。" << std::endl;
delete prep_stmt;
} catch (sql::SQLException &e) {
std::cerr << "\n--- SQL Exception ---" << std::endl;
std::cerr << "Message: " << e.what() << std::endl;
std::cerr << "SQLState: " << e.getSQLState() << std::endl;
std::cerr << "ErrorCode: " << e.getErrorCode() << std::endl;
return EXIT_FAILURE;
}
// 5. 关闭连接并释放资源
delete con;
std::cout << "\nC++: 数据库连接已关闭。" << std::endl;
return EXIT_SUCCESS;
}
注意: 同样,请替换代码中的表名和列名。
3.3 编译与运行
使用以下命令编译 C++ 代码:
bash
g++ main.cpp -o main_cpp -lmysqlcppconn
运行程序:
bash
./main_cpp
四、对比与最佳实践
| 特性 | C (libmysqlclient) |
C++ (Connector/C++) |
推荐场景 |
|---|---|---|---|
| API 风格 | 过程式 (Procedural) | 面向对象 (Object-Oriented) | C++ 项目首选 C++ API。 |
| 易用性 | 较低,需手动管理资源。 | 较高,接口更清晰,RAII 风格。 | 追求开发效率和代码可读性选 C++。 |
| 安全性 | 需手动拼接 SQL,易出错,有注入风险。 | 内置 PreparedStatement,天然防 SQL 注入。 |
强烈推荐使用预处理语句! |
| 性能 | 极致性能,开销最小。 | 性能优秀,略高于 C API 开销,但可忽略。 | 对性能要求极致的底层应用可选 C。 |
| 跨平台 | 优秀 | 优秀 | 两者均可。 |
核心最佳实践
- 始终使用预处理语句 (
Prepared Statements):这是防止 SQL 注入攻击最有效的方法,C++ 的 Connector/C++ 对此提供了原生支持。 - 完善的错误处理:数据库操作随时可能出错(网络问题、SQL 语法错误等)。C 中检查每个函数的返回值,C++ 中使用
try...catch捕获异常。 - 资源管理:确保所有分配的资源(连接、结果集、语句对象)都被正确释放,避免内存泄漏。
- 配置分离:不要将数据库密码等敏感信息硬编码在代码中,应使用配置文件或环境变量。
希望这篇文章能帮助你顺利开启 C/C++ 与 MySQL 数据库的交互之旅!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)