`mysql_query()` 数据库查询函数

1) 函数的概念与用途

mysql_query() 是 MySQL C API 中的核心函数,用于向 MySQL 服务器发送 SQL 查询语句。这个函数充当了 C/C++ 应用程序与 MySQL 数据库之间的桥梁,允许程序执行各种数据库操作。

可以将 mysql_query() 想象成一个"数据库信使":你给它一个 SQL 查询指令,它就把这个指令传递给 MySQL 服务器,然后带回执行结果。无论是数据查询、插入、更新还是删除,都需要通过这个函数来执行。

典型应用场景包括:

  • 数据检索:执行 SELECT 语句查询数据库中的数据
  • 数据操作:执行 INSERT、UPDATE、DELETE 语句修改数据
  • 数据库管理:执行 CREATE、ALTER、DROP 等DDL语句
  • 事务控制:执行 BEGIN、COMMIT、ROLLBACK 等事务操作
  • 存储过程调用:执行 CALL 语句调用存储过程

2) 函数的声明与出处

mysql_query() 是 MySQL C API 的一部分,声明在 mysql.h 头文件中。

c 复制代码
#include <mysql.h>

int mysql_query(MYSQL *mysql, const char *stmt_str);

要使用这个函数,需要链接 MySQL 客户端库(libmysqlclient)。

3) 参数详解:连接对象和SQL语句

  • MYSQL *mysql

    • 作用 :指向 MySQL 连接句柄的指针,由 mysql_init()mysql_real_connect() 创建
    • 要求:必须是有效的、已连接的数据库连接句柄
  • const char *stmt_str

    • 作用:要执行的 SQL 查询语句,以空字符结尾的 C 字符串
    • 要求:必须是有效的 SQL 语句,不应包含分号结尾(除非在多个语句中)
    • 注意 :SQL 语句中不应包含二进制数据(对于二进制数据应使用 mysql_real_query()

4) 返回值:执行状态

  • 返回值类型int

  • 返回值含义

    • 成功:返回 0
    • 失败:返回非零值
  • 错误处理

    • 失败时可以使用 mysql_error()mysql_errno() 获取错误信息
    • 成功执行 SELECT 查询后,需要使用 mysql_store_result()mysql_use_result() 获取结果集

5) 实战演示:多种使用场景

示例 1:基础查询操作

c 复制代码
#include <stdio.h>
#include <mysql.h>

int main() {
    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;
    
    // 初始化连接
    conn = mysql_init(NULL);
    if (conn == NULL) {
        fprintf(stderr, "mysql_init() failed\n");
        return 1;
    }
    
    // 连接到数据库
    if (mysql_real_connect(conn, "localhost", "user", "password", 
                          "database", 0, NULL, 0) == NULL) {
        fprintf(stderr, "Connection failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }
    
    // 执行查询
    if (mysql_query(conn, "SELECT id, name, email FROM users")) {
        fprintf(stderr, "Query failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }
    
    // 获取结果集
    res = mysql_store_result(conn);
    if (res == NULL) {
        fprintf(stderr, "Store result failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }
    
    // 处理结果
    printf("ID\tName\tEmail\n");
    while ((row = mysql_fetch_row(res)) != NULL) {
        printf("%s\t%s\t%s\n", row[0], row[1], row[2]);
    }
    
    // 清理资源
    mysql_free_result(res);
    mysql_close(conn);
    
    return 0;
}

示例 2:数据插入操作

c 复制代码
#include <stdio.h>
#include <mysql.h>

int main() {
    MYSQL *conn;
    
    // 初始化并连接数据库(省略错误检查简化代码)
    conn = mysql_init(NULL);
    mysql_real_connect(conn, "localhost", "user", "password", "testdb", 0, NULL, 0);
    
    // 插入数据
    if (mysql_query(conn, "INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com')")) {
        fprintf(stderr, "Insert failed: %s\n", mysql_error(conn));
    } else {
        printf("Insert successful, affected rows: %lld\n", mysql_affected_rows(conn));
    }
    
    mysql_close(conn);
    return 0;
}

示例 3:事务处理

c 复制代码
#include <stdio.h>
#include <mysql.h>

int main() {
    MYSQL *conn;
    
    conn = mysql_init(NULL);
    mysql_real_connect(conn, "localhost", "user", "password", "testdb", 0, NULL, 0);
    
    // 开始事务
    mysql_query(conn, "START TRANSACTION");
    
    // 执行多个操作
    if (mysql_query(conn, "UPDATE accounts SET balance = balance - 100 WHERE id = 1")) {
        mysql_query(conn, "ROLLBACK");
        fprintf(stderr, "Transfer failed\n");
    } else if (mysql_query(conn, "UPDATE accounts SET balance = balance + 100 WHERE id = 2")) {
        mysql_query(conn, "ROLLBACK");
        fprintf(stderr, "Transfer failed\n");
    } else {
        mysql_query(conn, "COMMIT");
        printf("Transfer successful\n");
    }
    
    mysql_close(conn);
    return 0;
}

6) 编译方式与注意事项

编译命令:

bash 复制代码
gcc -o mysql_demo mysql_demo.c $(mysql_config --cflags) $(mysql_config --libs)

或者显式指定路径:

bash 复制代码
gcc -o mysql_demo mysql_demo.c -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient

关键注意事项:

  1. SQL注入风险:不要直接将用户输入拼接到SQL语句中,使用参数化查询或转义函数
  2. 错误处理:始终检查每个MySQL API调用的返回值
  3. 资源清理:确保释放所有分配的资源(结果集、连接等)
  4. 二进制数据 :对于包含二进制数据的查询,使用 mysql_real_query() 代替
  5. 多语句查询:默认情况下,MySQL不允许在单个查询中执行多个语句(出于安全考虑)
  6. 性能考虑 :对于大量数据的检索,考虑使用 mysql_use_result() 而不是 mysql_store_result()

7) 执行结果说明

示例 1 可能输出:

复制代码
ID      Name    Email
1       Alice   alice@example.com
2       Bob     bob@example.com
3       Charlie charlie@example.com

展示了如何执行SELECT查询并处理结果集。

示例 2 可能输出:

复制代码
Insert successful, affected rows: 1

显示了插入操作的成功执行,并获取受影响的行数。

示例 3 可能输出:

复制代码
Transfer successful

演示了如何使用事务确保多个操作的原子性。

8) 总结:mysql_query() 的工作流程与价值

mysql_query() 的工作流程可以总结如下:
是 否 是 否 调用 mysql_query(conn, sql) 验证连接和参数有效性 将SQL语句发送到MySQL服务器 服务器执行成功? 返回0
执行成功 返回非零值
执行失败 是SELECT查询? 使用mysql_store_result
或mysql_use_result获取结果 使用mysql_affected_rows
获取受影响行数 使用mysql_error
获取错误信息

mysql_query() 是 MySQL C API 的核心函数,它的价值在于:

  1. 数据库交互:提供了C/C++程序与MySQL数据库交互的主要手段
  2. 灵活性:支持执行各种类型的SQL语句
  3. 简单易用:接口简单,易于理解和使用

MySQL数据库操作 如何选择执行函数? 执行文本SQL语句 使用mysql_query 执行包含二进制数据的SQL 使用mysql_real_query 执行参数化查询 使用预处理语句
mysql_stmt_prepare等

最佳实践建议:

  1. 使用预处理语句:对于用户输入的数据,使用预处理语句防止SQL注入
  2. 彻底的错误处理:检查每个数据库操作的返回值
  3. 资源管理:确保正确释放所有数据库资源
  4. 连接复用**:在可能的情况下复用数据库连接,避免频繁连接断开
  5. 安全考虑:不要在代码中硬编码数据库凭据,使用安全配置方式

mysql_query() 虽然简单,但却是 MySQL C API 编程的基础。掌握它的正确用法和注意事项,对于开发稳定、安全的数据库应用程序至关重要。无论是简单的数据查询还是复杂的事务处理,mysql_query() 都是连接C/C++应用与MySQL数据库的重要桥梁。

相关推荐
携欢2 小时前
Portswigger靶场之 Blind SQL injection with time delays通关秘籍
数据库·sql
十八旬2 小时前
苍穹外卖项目实战(日记十)-记录实战教程及问题的解决方法-(day3-2)新增菜品功能完整版
java·开发语言·spring boot·mysql·idea·苍穹外卖
FeBaby2 小时前
mysql为什么使用b+树不使用红黑树
数据库·b树·mysql
青草地溪水旁2 小时前
`lock()` 和 `unlock()` 线程同步函数
linux·c++·c
ZHZCE3 小时前
在 Ubuntu 20.04 上安装 MySQL 8.0
mysql
令狐少侠20113 小时前
如何使用navicat连接容器中的mysql数据库
mysql·docker
玩转数据库管理工具FOR DBLENS3 小时前
精准测试的密码:解密等价类划分,让Bug无处可逃
数据库·单元测试·测试用例·bug·数据库开发
AAA修煤气灶刘哥3 小时前
踩完 10 个坑后,我把多表查询 + MyBatis 动态 SQL 写成了干货
java·数据库·后端
怕浪猫3 小时前
MySQL 多表查询的应用
sql·mysql