mysql.h学习记录


简介

mysql.h 是 MySQL C API 的主要头文件,它为 C 开发者提供了一套函数和定义,以与 MySQL 服务器交互。这些函数和定义使得开发者能够编写应用程序,实现与 MySQL 服务器的连接、执行查询、检索结果等操作。

以下是一些常见的函数及其在 mysql.h 中的简要介绍:

  1. 连接和关闭
  • mysql_init(MYSQL *mysql): 初始化一个 MYSQL 对象。
  • mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag): 与 MySQL 服务器建立连接。
  • mysql_close(MYSQL *mysql): 关闭一个 MySQL 连接。
  1. 执行查询
  • mysql_query(MYSQL *mysql, const char *q): 向服务器发送一个查询。
  • mysql_real_query(MYSQL *mysql, const char *q, unsigned long length): 类似于 mysql_query,但是你可以指定查询字符串的长度。
  1. 结果处理
  • mysql_store_result(MYSQL *mysql): 为一个 SELECT 或 SHOW 查询检索完整的结果集。
  • mysql_use_result(MYSQL *mysql): 初始化为逐行检索的结果集。与 mysql_store_result 不同,此方法允许在结果集上启动一个检索,然后在每次调用 mysql_fetch_row() 时检索行,而不会预先检索所有行。
  • mysql_fetch_row(MYSQL_RES *result): 从结果集中获取下一行。
  • mysql_fetch_lengths(MYSQL_RES *result): 返回最近检索的行的每个字段的长度。
  • mysql_free_result(MYSQL_RES *result): 释放一个结果集使用的内存。
  1. 错误处理
  • mysql_error(MYSQL *mysql): 返回最近的调用的错误字符串。
  • mysql_errno(MYSQL *mysql): 返回最近的调用的错误编号。
  1. 转义和字符串处理
  • mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length): 对字符串进行转义,以便安全地发送到服务器。
  • mysql_escape_string(char *to, const char *from, unsigned long from_length): 这是 mysql_real_escape_string 的旧版本,不再建议使用。
  1. 信息检索
  • mysql_num_rows(MYSQL_RES *res): 返回结果集中的行数。
  • mysql_num_fields(MYSQL_RES *res): 返回结果集中的字段数。
  • mysql_field_count(MYSQL *mysql): 返回最近查询的列数。对于 SELECT 查询,这通常是结果集的字段数。
  1. 预备语句
  • 还有一些函数支持预备语句,但基本用法主要涉及 mysql_stmt_initmysql_stmt_preparemysql_stmt_executemysql_stmt_fetch 和相关函数。这些函数使你能够准备 SQL 语句、绑定参数、执行和检索结果。


MYSQL结构体

typedef struct MYSQL {
  NET net;                     /* Communication parameters */
  unsigned char *connector_fd; /* ConnectorFd for SSL */
  char *host, *user, *passwd, *unix_socket, *server_version, *host_info;
  char *info, *db;
  struct CHARSET_INFO *charset;
  MYSQL_FIELD *fields;
  struct MEM_ROOT *field_alloc;
  uint64_t affected_rows;
  uint64_t insert_id;      /* id if insert on table with NEXTNR */
  uint64_t extra_info;     /* Not used */
  unsigned long thread_id; /* Id for connection in server */
  unsigned long packet_length;
  unsigned int port;
  unsigned long client_flag, server_capabilities;
  unsigned int protocol_version;
  unsigned int field_count;
  unsigned int server_status;
  unsigned int server_language;
  unsigned int warning_count;
  struct st_mysql_options options;
  enum mysql_status status;
  enum enum_resultset_metadata resultset_metadata;
  bool free_me;   /* If free in mysql_close */
  bool reconnect; /* set to 1 if automatic reconnect */

  /* session-wide random string */
  char scramble[SCRAMBLE_LENGTH + 1];

  LIST *stmts; /* list of all statements */
  const struct MYSQL_METHODS *methods;
  void *thd;
  /*
    Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag
    from mysql_stmt_close if close had to cancel result set of this object.
  */
  bool *unbuffered_fetch_owner;
  void *extension;
} MYSQL;

MYSQL 结构体在 MySQL C API 中扮演了核心角色,它代表了一个客户端到 MySQL 服务器的连接。这个结构体包含了大量的字段,用于存储连接的状态、配置、以及与服务器通信所需的各种信息。下面是对这个结构体中各个字段的详细解释:

基础连接信息

  1. NET net;
    这个字段包含了用于与 MySQL 服务器通信的网络参数。它是一个 NET 类型的结构体,其中可能包含了套接字信息、缓冲区、以及网络读写相关的函数指针等。
  1. unsigned char *connector_fd;
    这个字段是一个指向无符号字符的指针,用于存储与 SSL 连接相关的文件描述符或句柄。在 SSL 通信中,它可能用于标识底层的套接字或其他通信资源。
  1. char *host, *user, *passwd, *unix_socket, *server_version, *host_info;
    这些字段存储了连接的基本信息,如主机名、用户名、密码等。unix_socket 用于指定 Unix 域套接字路径(如果适用)。server_version 存储了服务器的版本字符串,而 host_info 则可能包含了关于连接主机的额外信息。
  1. char *info, *db;
    info 字段通常用于存储服务器返回的状态或错误信息。db 字段存储了当前选定的数据库名称。

字符集和字段信息

  1. struct CHARSET_INFO *charset;
    这个字段是一个指向 CHARSET_INFO 结构体的指针,用于表示当前连接的字符集设置。
  1. MYSQL_FIELD *fields;
    这个字段是一个指向 MYSQL_FIELD 结构体的数组(实际上是一个指针,指向数组的首元素),用于存储查询结果集的字段信息。每个 MYSQL_FIELD 结构体都包含了关于一个字段的详细信息,如字段名、类型、长度等。
  1. struct MEM_ROOT *field_alloc;
    这个字段是一个指向 MEM_ROOT 结构体的指针,用于管理字段信息的内存分配。MySQL C API 使用自己的内存管理系统来分配和释放内存,MEM_ROOT 是这个系统中的一个关键组件。

查询状态和服务器信息

  1. uint64_t affected_rows, insert_id, extra_info;
    affected_rows 存储了最近一次查询影响的行数。insert_id 存储了最后一次 INSERT 查询生成的 AUTO_INCREMENT 值(如果适用的话)。extra_info 是一个保留字段,当前未使用。
  1. unsigned long thread_id, packet_length;
    thread_id 存储了服务器上为这个连接分配的线程 ID。packet_length 用于存储当前正在处理的网络数据包的长度。
  1. unsigned int port;
    这个字段存储了用于连接的服务器端口号。
  1. unsigned long client_flag, server_capabilities;
    这些字段包含了客户端和服务器的能力标志,用于在通信过程中协商和确定双方支持的功能。
  1. unsigned int protocol_version, field_count, server_status, server_language, warning_count;
    这些字段存储了与协议版本、字段数量、服务器状态、服务器语言和警告计数相关的信息。

连接选项和状态

  1. struct st_mysql_options options;
    这个字段是一个包含连接选项的结构体,如超时设置、SSL 选项等。这些选项在建立连接时通过 mysql_real_connect() 等函数进行设置。
  1. enum mysql_status status;
    这个字段是一个枚举值,表示连接的当前状态,如就绪、关闭等。
  1. enum enum_resultset_metadata resultset_metadata;
    这个字段是一个枚举值,表示结果集的元数据状态或类型。它可能与查询结果集的格式和可用性有关。然而,请注意,在标准的 MySQL C API 中,并没有直接定义名为 enum_resultset_metadata 的枚举类型。这可能是一个自定义扩展或特定版本的 API 中的内容。在标准的 API 中,更常见的是与结果集处理相关的其他结构体和函数。

其他连接相关字段

  1. bool free_me, reconnect;
    这些布尔标志用于控制连接的行为。free_me 指示在关闭连接时是否应释放与此连接相关的内存。reconnect 指示在连接丢失时是否应自动尝试重新连接。
  1. char scramble[SCRAMBLE_LENGTH + 1];
    这个字段存储了一个会话范围的随机字符串,通常用于身份验证过程中的密码加密或散列。
  1. LIST *stmts;
    这个字段是一个指向语句列表的指针,可能包含了与此连接关联的所有已准备或正在执行的语句。然而,请注意,在标准的 MySQL C API 中,并没有直接定义名为 LIST 的数据结构。这可能是一个自定义扩展或特定版本的 API 中的内容。在标准的 API 中,更常见的是使用 MYSQL_STMT 结构体来处理预准备语句。
  1. const struct MYSQL_METHODS *methods;
    这个字段是一个指向 MYSQL_METHODS 结构体的指针,该结构体包含了指向实现各种连接方法的函数的指针。这使得 API 的内部实现可以与特定的连接方法(如 TCP/IP、Unix 套接字等)解耦。然而,请注意,在标准的 MySQL C API 中,并没有直接定义名为 MYSQL_METHODS 的结构体。这可能是一个自定义扩展或特定版本的 API 中的内容。在标准的 API 中,连接方法的实现通常是隐藏的,并通过 API 提供的函数进行访问。
  1. void *thd;
    这个字段是一个通用指针,可能用于存储与线程或连接相关的内部数据。其确切用途取决于 MySQL C API 的内部实现。
  1. bool *unbuffered_fetch_owner;
    这个字段是一个指向布尔标志的指针,用于指示是否应使用无缓冲获取来检索结果集。这通常与性能优化和内存使用有关。然而,请注意,在标准的 MySQL C API 中,并没有直接暴露这个字段。无缓冲获取通常是通过其他方式(如设置特定的选项或使用特定的函数)来控制的。
  1. void *extension;
    这个字段是一个通用扩展指针,可能用于存储与特定连接或会话相关的额外数据或状态信息。其确切用途取决于应用程序或 MySQL C API 的扩展。在标准的 API 中,这个字段通常不用于公共用途,而是保留给内部实现或特定扩展使用。


MYSQL_RES

typedef struct MYSQL_RES {
  uint64_t row_count;
  MYSQL_FIELD *fields;
  struct MYSQL_DATA *data;
  MYSQL_ROWS *data_cursor;
  unsigned long *lengths; /* column lengths of current row */
  MYSQL *handle;          /* for unbuffered reads */
  const struct MYSQL_METHODS *methods;
  MYSQL_ROW row;         /* If unbuffered read */
  MYSQL_ROW current_row; /* buffer to current row */
  struct MEM_ROOT *field_alloc;
  unsigned int field_count, current_field;
  bool eof; /* Used by mysql_fetch_row */
  /* mysql_stmt_close() had to cancel this result */
  bool unbuffered_fetch_cancelled;
  enum enum_resultset_metadata metadata;
  void *extension;
} MYSQL_RES;

这是一个定义了一个结构体 MYSQL_RES 的C代码段,它代表了MySQL数据库查询操作返回的结果集。该结构体中包含了多个成员,这些成员提供了访问查询结果的方式和关于查询结果的信息。以下是对各个成员的解释:

  1. row_count:一个64位无符号整数,表示结果集中的行数。
  2. fields:一个指向MYSQL_FIELD结构体的指针,用于存储结果集中列的信息。
  3. data:一个指向MYSQL_DATA结构体的指针,包含实际的查询数据。
  4. data_cursor:一个指向MYSQL_ROWS结构体的指针,用于追踪当前读取到哪一行的数据。
  5. lengths:一个无符号长整型的指针,存储当前行中每列数据的长度。
  6. handle:一个指向MYSQL结构体的指针,它是数据库连接的句柄,用于无缓冲的读取操作。
  7. methods:一个指向MYSQL_METHODS结构体的指针,这个结构体可能包含一些与特定MySQL结果集相关的函数指针。
  8. row:一个MYSQL_ROW类型的指针,如果执行了无缓冲读取,它会指向当前行的数据。
  9. current_row:一个MYSQL_ROW类型的指针,用作缓冲区来存储当前读取到的行数据。
  10. field_alloc:一个指向MEM_ROOT结构体的指针,可能与字段的内存分配有关。
  11. field_count:一个无符号整数,表示结果集中的列数。
  12. current_field:一个无符号整数,用于追踪当前读取到哪一列。
  13. eof:一个布尔值,当读取到结果集的末尾时会被设置为true
  14. unbuffered_fetch_cancelled:一个布尔值,如果无缓冲的读取操作被取消(如由于调用了mysql_stmt_close()),则会被设置为true
  15. metadata:一个枚举类型,包含有关结果集的元数据信息。
  16. extension:一个指向未指定类型的指针,它可能被用作存储与结果集相关的其他信息的扩展区域。


mysql_init

mysql_init(MYSQL *mysql) 是 MySQL C API 中的一个函数,用于初始化一个 MYSQL 结构,该结构在后续的操作中将被用作与 MySQL 服务器的连接句柄。这个结构包含了与 MySQL 服务器通信所需的所有状态信息。

函数原型

在 MySQL 的头文件中,mysql_init 函数的原型通常如下所示:

MYSQL *mysql_init(MYSQL *mysql);

参数

  • MYSQL *mysql: 指向一个 MYSQL 结构的指针。如果传递的是 NULL,则函数会分配一个新的 MYSQL 结构并返回指向它的指针。如果传递的是一个已存在的 MYSQL 结构的地址,那么该结构会被初始化。

返回值

  • 如果初始化成功,函数返回指向 MYSQL 结构的指针(可能与传入的指针相同,也可能是新分配的)。
  • 如果内存分配失败,返回 NULL

使用示例

下面是一个使用 mysql_init 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;

    // 初始化 MYSQL 结构
    conn = mysql_init(NULL);

    if (conn == NULL) {
        fprintf(stderr, "mysql_init() failed\n");
        return 1;
    }

    // 设置连接参数(这里只是示例,并不完整)
    mysql_options(conn, MYSQL_SET_CHARSET_NAME, "utf8");

    // 连接到 MySQL 服务器(需要填写正确的连接信息)
    if (mysql_real_connect(conn, "host", "user", "password", "database", 0, NULL, 0) == NULL) {
        fprintf(stderr, "mysql_real_connect() failed\n");
        mysql_close(conn); // 即使连接失败,也应该调用 mysql_close 来释放已分配的资源
        return 1;
    }

    // ... 执行其他数据库操作 ...

    // 关闭连接
    mysql_close(conn);

    return 0;
}

在这个示例中,我们首先调用 mysql_init(NULL) 来初始化一个新的 MYSQL 结构,并将其地址存储在 conn 指针中。然后,我们设置了一些连接选项(在这个例子中只是设置了字符集为 UTF-8),并尝试使用 mysql_real_connect 连接到 MySQL 服务器。如果连接成功,我们可以执行其他数据库操作,最后使用 mysql_close 关闭连接。

注意事项

  • 在调用 mysql_init 之后,应确保在不再需要 MYSQL 结构时调用 mysql_close 来释放资源,即使连接失败也是如此。这是因为 mysql_init 可能会分配一些内存或其他资源给 MYSQL 结构。
  • 如果你传递一个非空的 MYSQL 结构给 mysql_init,它会重置该结构的内容,但不会释放任何已分配的内存。因此,通常建议在使用完一个 MYSQL 结构后调用 mysql_close,然后再重新使用它来建立新的连接。
  • 在多线程环境中使用 MySQL C API 时,需要确保线程安全。如果 MySQL 库是以线程安全的方式编译的(可以通过调用 mysql_thread_safe() 来检查),那么可以在不同的线程中同时使用多个 MYSQL 结构。但是,每个线程都应该有自己的 MYSQL 结构,并且不应该在多个线程之间共享同一个结构。


mysql_real_connect

mysql_real_connect() 是 MySQL C API 中的一个关键函数,用于建立与 MySQL 服务器的实际连接。在调用此函数之前,通常先使用 mysql_init() 初始化一个 MYSQL 结构。mysql_real_connect() 尝试使用这个已初始化的结构来连接到数据库服务器。

函数原型

在 MySQL 的头文件中,mysql_real_connect() 函数的原型通常如下所示:

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
                          const char *passwd, const char *db, unsigned int port,
                          const char *unix_socket, unsigned long client_flag);

参数

  • MYSQL *mysql: 指向一个已初始化的 MYSQL 结构的指针。
  • const char *host: MySQL 服务器的主机名或 IP 地址。如果是本地服务器,可以使用 localhost127.0.0.1
  • const char *user: 用于连接的用户名。
  • const char *passwd: 用户的密码。
  • const char *db: 要连接的数据库名。可以为 NULL,稍后再使用 mysql_select_db() 选择数据库。
  • unsigned int port: MySQL 服务器的端口号。如果服务器运行在默认端口上,此参数可以为 0
  • const char *unix_socket: 如果服务器运行在本地并通过 Unix 套接字接受连接,这里指定套接字的路径。对于 TCP/IP 连接,此参数应为 NULL
  • unsigned long client_flag: 客户端标志,用于设置各种连接选项。这可以是多个选项的按位或(bitwise OR)。

返回值

  • 如果连接成功,函数返回指向 MYSQL 结构的指针(通常与传入的 mysql 参数相同)。
  • 如果连接失败,返回 NULL。可以通过调用 mysql_error() 获取错误信息。

使用示例

下面是一个使用 mysql_real_connect() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;

    // 初始化 MYSQL 结构
    conn = mysql_init(NULL);
    if (conn == NULL) {
        fprintf(stderr, "mysql_init() failed\n");
        return 1;
    }

    // 连接到 MySQL 服务器
    if (mysql_real_connect(conn, "localhost", "username", "password", "database", 0, NULL, 0) == NULL) {
        fprintf(stderr, "mysql_real_connect() failed: %s\n", mysql_error(conn));
        mysql_close(conn); // 即使连接失败,也应该调用 mysql_close 来释放已分配的资源(尽管在这种情况下可能不是必需的)
        return 1;
    }

    // ... 执行其他数据库操作 ...

    // 关闭连接
    mysql_close(conn);

    return 0;
}

注意:在实际代码中,不应该硬编码用户名、密码或数据库名。这些应该从配置文件、环境变量或命令行参数中安全地获取。此外,错误处理应该更加完善,包括检查 mysql_real_connect() 调用后的连接状态以及执行其他数据库操作时可能出现的错误。

注意事项

  • 在调用 mysql_real_connect() 之前,确保已经使用 mysql_init() 初始化了 MYSQL 结构。
  • 如果连接失败,务必检查并处理错误。可以使用 mysql_error() 函数获取详细的错误信息。
  • 连接成功后,可以使用其他 MySQL C API 函数执行 SQL 查询、处理结果集等。
  • 完成所有数据库操作后,使用 mysql_close() 关闭连接以释放资源。


mysql_close

mysql_close() 是 MySQL C API 中的一个函数,用于关闭一个与 MySQL 服务器的连接,并断开与该服务器的所有通信。当你使用 mysql_init()mysql_real_connect() 成功建立连接并完成所有数据库操作后,应该调用 mysql_close() 来释放分配给该连接的所有资源。

函数原型

在 MySQL 的头文件中,mysql_close() 函数的原型通常如下所示:

int mysql_close(MYSQL *mysql);

参数

  • MYSQL *mysql: 指向一个已连接的 MYSQL 结构的指针。这个结构通常是通过 mysql_init() 初始化并通过 mysql_real_connect() 连接到服务器的。

返回值

  • 如果关闭连接成功,函数返回 0
  • 如果关闭连接失败,返回非零值。可以通过调用 mysql_error() 获取错误信息。

然而,值得注意的是,在较新版本的 MySQL C API 中(例如 MySQL Connector/C 8.0 及更高版本),mysql_close() 的返回值行为可能有所不同。在这些版本中,即使连接已经关闭或出现问题,mysql_close() 也可能总是返回 0,表示成功。这是因为该函数的主要目的是释放资源,而不是报告连接状态。因此,依赖 mysql_close() 的返回值来判断连接是否成功关闭可能不是一个好主意;相反,你应该确保在调用 mysql_close() 之前正确处理所有可能的错误情况。

使用示例

下面是一个使用 mysql_close() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;

    // 初始化 MYSQL 结构并连接到服务器(代码省略)...

    // 关闭连接
    if (mysql_close(conn) != 0) {
        fprintf(stderr, "mysql_close() failed: %s\n", mysql_error(conn));
        // 注意:在调用 mysql_close() 后使用 mysql_error() 可能是不安全的,因为连接已经关闭。
        // 这个示例仅用于演示目的,并不推荐在实际代码中使用。
    } else {
        printf("Connection closed successfully.\n");
    }

    return 0;
}

重要提示:在实际应用中,你不应该在调用 mysql_close() 后使用 mysql_error(),因为当连接关闭时,与该连接相关联的所有资源(包括错误消息缓冲区)都可能被释放或变得不可用。上面的示例仅用于演示目的,并不符合最佳实践。通常,你应该在关闭连接之前处理所有可能的错误情况。

注意事项

  • 在多线程环境中使用时,确保每个线程都有自己的 MYSQL 结构,并且不要在线程之间共享这些结构。每个线程都应该负责关闭它自己的连接。
  • 即使你的应用程序在关闭连接之前遇到了错误或异常终止,也应该尽力确保 mysql_close() 被调用以释放资源。这可以通过使用诸如 atexit() 的函数或在适当的清理代码中来实现。
  • 在某些情况下,如果连接由于网络问题或服务器故障而意外断开,调用 mysql_close() 仍然是有用的,因为它会尝试清理客户端端的任何挂起资源。然而,它不能重新建立已经丢失的连接或解决服务器端的问题。


mysql_query

mysql_query() 是 MySQL C API 中的一个函数,用于向 MySQL 服务器发送 SQL 查询。这个函数在较新版本的 MySQL Connector/C 中已被标记为过时(deprecated),推荐使用更现代、更安全的函数,如 mysql_real_query() 或预处理语句相关的函数。不过,为了理解旧代码或向后兼容,了解 mysql_query() 的工作方式仍然是有用的。

函数原型

在 MySQL 的头文件中,mysql_query() 函数的原型通常如下所示:

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

参数

  • MYSQL *mysql: 指向一个已连接的 MYSQL 结构的指针。这个结构是通过 mysql_init() 初始化并通过 mysql_real_connect() 连接到服务器的。
  • const char *query: 一个包含 SQL 查询语句的以空字符(\0)结尾的字符串。

返回值

  • 如果查询成功,函数返回 0
  • 如果查询失败,返回非零值。可以通过调用 mysql_error() 获取错误信息。

使用示例

下面是一个使用 mysql_query() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;

    // 初始化 MYSQL 结构并连接到服务器(代码省略)...

    // 发送 SQL 查询
    if (mysql_query(conn, "SELECT * FROM mytable")) {
        fprintf(stderr, "mysql_query() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 处理查询结果(代码省略)...

    // 关闭连接
    mysql_close(conn);

    return 0;
}

注意事项

  1. 安全性mysql_query() 不支持参数化查询,因此直接将用户输入拼接到 SQL 语句中可能导致 SQL 注入攻击。为了避免这种安全风险,应该使用预处理语句或确保所有输入都经过适当的转义。

  2. 多语句查询mysql_query() 不支持多语句查询(即一个字符串中包含多个由分号分隔的 SQL 语句)。尝试执行这样的查询可能会导致错误。

  3. 错误处理:如果 mysql_query() 失败,应该检查返回值并使用 mysql_error() 来获取详细的错误信息。此外,即使查询成功,也应该检查 mysql_store_result()mysql_use_result() 的返回值,因为这些函数可能会在尝试检索结果时遇到错误。

  4. 已过时:如前所述,mysql_query() 在较新版本的 MySQL Connector/C 中已被标记为过时。对于新开发的项目,建议使用更现代、更安全的 API 函数。

  5. 结果处理:执行 SELECTSHOWDESCRIBEEXPLAIN 查询后,必须使用 mysql_store_result()mysql_use_result() 来获取结果集。对于其他类型的查询(如 INSERTUPDATEDELETE),可以直接检查 mysql_query() 的返回值来确定操作是否成功。不过,即使对于这些查询类型,也可能需要调用 mysql_affected_rows() 来获取受影响的行数或 mysql_insert_id() 来获取最后插入的行的自增 ID。



mysql_real_query

mysql_real_query() 是 MySQL C API 中的一个函数,用于向 MySQL 服务器发送 SQL 查询。与 mysql_query() 相比,mysql_real_query() 提供了更多的灵活性,并且通常被推荐用于发送查询,特别是在需要处理包含二进制数据或特殊字符的查询时。

函数原型

在 MySQL 的头文件中,mysql_real_query() 函数的原型通常如下所示:

int mysql_real_query(MYSQL *mysql, const char *query, unsigned int length);

参数

  • MYSQL *mysql: 指向一个已连接的 MYSQL 结构的指针。这个结构是通过 mysql_init() 初始化并通过 mysql_real_connect() 连接到服务器的。
  • const char *query: 一个包含 SQL 查询语句的字符串。与 mysql_query() 不同,这个字符串不需要以空字符(\0)结尾,因为 length 参数指定了查询的长度。
  • unsigned int length: 查询字符串 query 的长度。这允许发送包含空字符的查询。

返回值

  • 如果查询成功,函数返回 0
  • 如果查询失败,返回非零值。可以通过调用 mysql_error() 获取错误信息。

使用示例

下面是一个使用 mysql_real_query() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>
#include <string.h>

int main() {
    MYSQL *conn;
    const char *query = "SELECT * FROM mytable";
    unsigned int query_len = strlen(query);

    // 初始化 MYSQL 结构并连接到服务器(代码省略)...

    // 发送 SQL 查询
    if (mysql_real_query(conn, query, query_len)) {
        fprintf(stderr, "mysql_real_query() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 处理查询结果(代码省略)...

    // 关闭连接
    mysql_close(conn);

    return 0;
}

注意事项

  1. 安全性:与 mysql_query() 一样,mysql_real_query() 本身不提供参数化查询的功能,因此直接将用户输入拼接到 SQL 语句中可能导致 SQL 注入攻击。为了避免这种安全风险,应该使用预处理语句或确保所有输入都经过适当的转义。

  2. 二进制数据:由于 mysql_real_query() 允许指定查询的长度,因此它特别适用于发送包含二进制数据或特殊字符(如空字符)的查询。

  3. 错误处理:如果 mysql_real_query() 失败,应该检查返回值并使用 mysql_error() 来获取详细的错误信息。此外,即使查询成功,也应该在处理结果时检查相关函数的返回值,以处理可能出现的错误。

  4. 多语句查询:与 mysql_query() 一样,mysql_real_query() 也不支持多语句查询。尝试执行包含多个由分号分隔的 SQL 语句的查询可能会导致错误。

  5. 结果处理:对于 SELECTSHOWDESCRIBEEXPLAIN 等查询类型,发送查询后需要使用如 mysql_store_result()mysql_use_result() 的函数来获取结果集。对于修改数据的查询(如 INSERTUPDATEDELETE),可以通过调用如 mysql_affected_rows() 的函数来获取受影响的行数等信息。



mysql_store_result

mysql_store_result() 是 MySQL C API 中的一个函数,用于检索并存储从服务器发送到客户端的完整结果集。当你执行一个 SELECT 查询或其他返回结果集的查询时,你需要使用这个函数(或类似的函数,如 mysql_use_result())来获取结果。

函数原型

在 MySQL 的头文件中,mysql_store_result() 函数的原型通常如下所示:

MYSQL_RES *mysql_store_result(MYSQL *mysql);

参数

  • MYSQL *mysql: 指向一个已连接的 MYSQL 结构的指针。这个结构是通过 mysql_init() 初始化并通过 mysql_real_connect() 连接到服务器的。

返回值

  • 如果成功,返回一个 MYSQL_RES 结果集结构的指针。
  • 如果失败,返回 NULL 指针。可以通过调用 mysql_error() 获取错误信息。

使用示例

下面是一个使用 mysql_store_result() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;

    // 初始化 MYSQL 结构并连接到服务器(代码省略)...

    // 发送 SQL 查询
    if (mysql_query(conn, "SELECT * FROM mytable")) {
        fprintf(stderr, "mysql_query() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 获取结果集
    res = mysql_store_result(conn);
    if (res == NULL) {
        fprintf(stderr, "mysql_store_result() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 遍历结果集
    while ((row = mysql_fetch_row(res)) != NULL) {
        // 处理每一行数据(代码省略)...
    }

    // 释放结果集
    mysql_free_result(res);

    // 关闭连接
    mysql_close(conn);

    return 0;
}

注意事项

  1. 内存管理mysql_store_result() 会为结果集中的所有行分配内存。这意味着对于大型结果集,这可能会占用大量内存。当你完成对结果集的处理后,应该使用 mysql_free_result() 释放结果集所占用的内存。

  2. mysql_use_result() 的区别:与 mysql_store_result() 不同,mysql_use_result() 不会为整个结果集分配内存,而是逐行从服务器检索结果。这可以减少内存使用,但可能会增加与服务器的通信开销,并且要求结果集在检索期间保持打开状态。

  3. 错误处理:如果 mysql_store_result() 失败,它将返回 NULL,并且你应该检查 mysql_error() 来获取详细的错误信息。

  4. 结果集元数据:通过 mysql_store_result() 获取的 MYSQL_RES 结构还包含有关结果集的元数据,如字段数、字段名称和字段类型。你可以使用如 mysql_num_fields()mysql_fetch_fields() 等函数来访问这些信息。

  5. 并发查询:在使用 mysql_store_result()mysql_use_result() 时,你不能在相同的连接上执行其他查询,直到你完全处理完当前的结果集并释放了相关资源。如果你需要在同一个连接上执行多个并发查询,你应该考虑使用不同的连接或使用连接池。



mysql_use_result

mysql_use_result() 是 MySQL C API 中的一个函数,用于初始化从 MySQL 服务器检索结果集的过程。与 mysql_store_result() 不同,这个函数不会将整个结果集一次性地拉取到客户端内存中,而是逐行拉取结果。这种方法在处理可能返回大量数据的查询时非常有用,因为它可以减少内存使用。

函数原型

在 MySQL 的头文件中,mysql_use_result() 函数的原型通常如下所示:

MYSQL_RES *mysql_use_result(MYSQL *mysql);

参数

  • MYSQL *mysql: 指向一个已连接的 MYSQL 结构的指针。这个结构是通过 mysql_init() 初始化并通过 mysql_real_connect() 连接到服务器的。

返回值

  • 如果成功,返回一个 MYSQL_RES 结果集结构的指针。
  • 如果失败,返回 NULL 指针。可以通过调用 mysql_error() 获取错误信息。

使用示例

下面是一个使用 mysql_use_result() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;

    // 初始化 MYSQL 结构并连接到服务器(代码省略)...

    // 发送 SQL 查询
    if (mysql_query(conn, "SELECT * FROM large_table")) {
        fprintf(stderr, "mysql_query() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 使用 mysql_use_result() 获取结果集
    res = mysql_use_result(conn);
    if (res == NULL) {
        fprintf(stderr, "mysql_use_result() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 逐行处理结果集
    while ((row = mysql_fetch_row(res)) != NULL) {
        // 对每一行数据执行操作(代码省略)...
    }

    // 结果集处理完后,释放资源
    mysql_free_result(res);

    // 在调用 mysql_free_result() 后,才能安全地发送下一个查询
    // ... 可能的其他查询操作 ...

    // 关闭连接
    mysql_close(conn);

    return 0;
}

注意事项

  1. 内存管理:与 mysql_store_result() 不同,mysql_use_result() 不会为整个结果集分配内存,而是在客户端逐行检索结果。这降低了内存使用量,但可能增加与服务器的通信次数。

  2. 未完成的结果集:如果在使用 mysql_use_result() 后未检索完整个结果集就尝试执行另一个查询,MySQL 服务器会返回错误。必须首先调用 mysql_free_result()(即使还没有检索完所有行),或者确保已经通过诸如 mysql_fetch_row() 的函数检索了所有行。

  3. 并发查询:由于 mysql_use_result() 会锁定与结果集相关联的连接,直到结果集被完全处理并释放,因此在处理结果集期间不能在该连接上执行其他查询。如果需要并发执行多个查询,应该使用不同的连接。

  4. 网络中断和错误恢复:由于 mysql_use_result() 逐行检索结果,因此它比 mysql_store_result() 更容易受到网络中断或服务器错误的影响。在这些情况下,应用程序应该准备好重新连接并重新执行查询。

  5. 与存储过程的兼容性:当与存储过程一起使用时,mysql_use_result() 可能会导致问题,因为存储过程可能会返回多个结果集。在这种情况下,通常更倾向于使用 mysql_store_result(),或者在可能的情况下,修改存储过程以避免返回多个结果集。



mysql_fetch_row

mysql_fetch_row() 是 MySQL C API 中的一个函数,用于从之前通过 mysql_store_result()mysql_use_result() 获取的结果集中检索一行数据。这个函数以数组的形式返回行中的数据,数组中的每个元素都是数据的字符串表示形式。

函数原型
在 MySQL 的头文件中,mysql_fetch_row() 函数的原型通常如下所示:

typedef char **MYSQL_ROW;                /* return data as array of strings */
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

参数

  • MYSQL_RES *result: 指向之前通过 mysql_store_result()mysql_use_result() 获取的 MYSQL_RES 结果集结构的指针。

返回值

  • 如果成功,返回一个 MYSQL_ROW 类型的指针,它是一个指向字符串数组的指针,数组中的每个元素代表结果集中的一列。
  • 如果没有更多的行可供检索,返回 NULL

使用示例

下面是一个使用 mysql_fetch_row() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;

    // 初始化 MYSQL 结构并连接到服务器(代码省略)...

    // 发送 SQL 查询
    if (mysql_query(conn, "SELECT id, name FROM users")) {
        fprintf(stderr, "mysql_query() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 获取结果集
    res = mysql_store_result(conn);
    if (res == NULL) {
        fprintf(stderr, "mysql_store_result() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 逐行处理结果集
    while ((row = mysql_fetch_row(res)) != NULL) {
        printf("ID: %s, Name: %s\n", row[0], row[1]);
    }

    // 释放结果集
    mysql_free_result(res);

    // 关闭连接
    mysql_close(conn);

    return 0;
}

注意事项

  1. 内存管理mysql_fetch_row() 返回的 MYSQL_ROW 指针指向的数据是内部结果集缓冲区的一部分。你不应该尝试释放这个指针或它指向的任何数据。当调用 mysql_free_result() 时,整个结果集和与之相关的内存将被释放。

  2. 数据类型mysql_fetch_row() 返回的所有数据都是字符串形式,即使原始数据是整数或其他类型。如果需要以原始数据类型访问数据,可以使用 mysql_fetch_field()mysql_fetch_lengths() 来获取字段的元数据,包括数据类型和长度。

  3. 空值和 NULL:如果结果集中的某个字段是 NULL,则 mysql_fetch_row() 返回的数组中对应的元素也将是 NULL。你应该检查每个元素是否为 NULL,以避免访问未初始化的内存。

  4. 错误处理:如果 mysql_fetch_row() 失败,它通常是因为结果集已经被完全检索或释放了。你应该检查返回值是否为 NULL,并相应地处理这种情况。在正常情况下,这个函数不会失败,除非传递了一个无效的结果集指针。

  5. mysql_fetch_array() 的区别mysql_fetch_array() 是 PHP 中的函数,不是 MySQL C API 的一部分。在 C API 中,你使用 mysql_fetch_row() 来获取行数据。如果你在使用 PHP,那么 mysql_fetch_array() 可以用来以关联数组、数字索引数组或二者兼有的形式获取行数据。然而,请注意 PHP 的 mysql_* 函数在较新的 PHP 版本中已被弃用,建议使用 mysqli 或 PDO 扩展来访问 MySQL 数据库。



mysql_fetch_lengths

mysql_fetch_lengths() 是 MySQL C API 中的一个函数,它用于获取通过 mysql_fetch_row() 或类似函数检索的行的列长度。当你从 MySQL 数据库检索数据时,特别是当处理文本或二进制数据时,了解每列数据的实际长度可能是很有用的。

函数原型

在 MySQL 的头文件中,mysql_fetch_lengths() 函数的原型通常如下所示:

unsigned long *mysql_fetch_lengths(MYSQL_RES *result);

参数

  • MYSQL_RES *result: 指向之前通过 mysql_store_result()mysql_use_result() 获取的 MYSQL_RES 结果集结构的指针。

返回值

  • 如果成功,返回一个指向无符号长整数数组的指针,该数组包含了结果集中当前行的每列的长度。数组的大小与结果集中的列数相同。
  • 如果失败或传递了无效的结果集指针,返回 NULL

使用示例

下面是一个使用 mysql_fetch_lengths() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;
    unsigned long *lengths;
    int i;

    // 初始化 MYSQL 结构并连接到服务器(代码省略)...

    // 发送 SQL 查询
    if (mysql_query(conn, "SELECT id, name, description FROM products")) {
        fprintf(stderr, "mysql_query() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 获取结果集
    res = mysql_store_result(conn);
    if (res == NULL) {
        fprintf(stderr, "mysql_store_result() failed: %s\n", mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // 逐行处理结果集
    while ((row = mysql_fetch_row(res)) != NULL) {
        lengths = mysql_fetch_lengths(res);
        if (lengths) {
            for (i = 0; i < mysql_num_fields(res); i++) {
                printf("Column %d length: %lu\n", i, lengths[i]);
            }
        }

        // 打印行数据(代码省略)...
    }

    // 释放结果集
    mysql_free_result(res);

    // 关闭连接
    mysql_close(conn);

    return 0;
}

注意事项

  1. 内存管理mysql_fetch_lengths() 返回的指针指向的是内部结果集缓冲区的一部分,你不应该尝试释放这个指针。当调用 mysql_free_result() 时,整个结果集和与之相关的内存将被释放。

  2. 空值和 NULL:如果结果集中的某个字段是 NULL,则对应的长度将是 0。这是因为 NULL 在 MySQL 中表示“无值”,因此没有长度可言。

  3. 错误处理:如果 mysql_fetch_lengths() 失败,通常是因为传递了一个无效的结果集指针。你应该检查返回值是否为 NULL,并相应地处理这种情况。在正常情况下,只要结果集有效且当前行有效,这个函数就不会失败。

  4. 使用时机mysql_fetch_lengths() 应在调用 mysql_fetch_row() 或其他类似函数之后立即调用,以确保获取的是当前行的列长度。如果在调用这些函数之前或之后调用了其他可能影响结果集状态的函数(如 mysql_data_seek()),则可能会得到错误的结果。



mysql_free_result

mysql_free_result() 是 MySQL C API 中的一个函数,用于释放之前通过 mysql_store_result(), mysql_use_result(), mysql_list_dbs(), mysql_list_tables(), mysql_list_fields(), 或者 mysql_list_processes() 等函数获取的结果集所占用的内存。当你使用这些函数获取结果集后,一旦完成对结果集的处理,就应该调用 mysql_free_result() 来释放相关的资源,以避免内存泄漏。

函数原型

在 MySQL 的头文件中,mysql_free_result() 函数的原型通常如下所示:

void mysql_free_result(MYSQL_RES *result);

参数

  • MYSQL_RES *result: 指向要释放的 MYSQL_RES 结果集结构的指针。

返回值

该函数没有返回值。它简单地释放了与给定结果集相关联的内存。

注意事项

  1. 释放时机:一旦你完成了对结果集的处理,就应该立即调用 mysql_free_result()。即使你打算再次使用相同的 MYSQL 连接进行其他查询,也应该先释放当前的结果集。

  2. 多次释放:对同一个结果集指针多次调用 mysql_free_result() 是不安全的。一旦一个结果集被释放,就不应该再次引用它,包括尝试再次释放它。

  3. 与其他 MySQL 函数的交互:在调用 mysql_free_result() 之后,你不应该再使用任何从该结果集中获取的数据(如通过 mysql_fetch_row() 获取的行数据)。此外,在释放结果集之后,与该结果集相关联的任何未处理的行或数据都将变得不可用。

  4. 连接关闭时的自动释放:当你调用 mysql_close() 来关闭一个 MySQL 连接时,与该连接相关联的所有未释放的结果集都将被自动释放。然而,为了良好的编程实践和资源管理,建议显式地释放每个结果集,而不是依赖这种自动释放机制。



mysql_error

mysql_error() 是 MySQL C API 中的一个函数,它用于检索最近调用的 MySQL 函数的错误消息。当你在使用 MySQL C API 与 MySQL 数据库交互时,可能会遇到各种错误情况,例如连接失败、查询错误等。在这些情况下,mysql_error() 可以帮助你获取具体的错误信息,从而进行适当的错误处理。

函数原型

在 MySQL 的头文件中,mysql_error() 函数的原型通常如下所示:

char *mysql_error(MYSQL *mysql);

参数

  • MYSQL *mysql: 指向一个 MYSQL 结构的指针,该结构表示一个与 MySQL 服务器的连接。通常,这个指针是通过调用 mysql_init()mysql_real_connect() 等函数获得的。

返回值

  • 如果最近调用的 MySQL 函数失败了,mysql_error() 返回一个描述错误的字符串。
  • 如果没有错误,或者 mysql 是一个无效的指针,返回值是未定义的(可能是 NULL 或一个空字符串,但不建议依赖这些行为)。

使用示例

下面是一个使用 mysql_error() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;

    // 初始化 MYSQL 结构
    conn = mysql_init(NULL);

    // 检查初始化是否成功
    if (conn == NULL) {
        fprintf(stderr, "mysql_init() failed\n");
        return 1;
    }

    // 连接到 MySQL 服务器
    if (mysql_real_connect(conn, "host", "user", "password", "database", 0, NULL, 0) == NULL) {
        fprintf(stderr, "mysql_real_connect() failed: %s\n", mysql_error(conn));
        mysql_close(conn); // 注意:在调用 mysql_error() 后,仍需要关闭连接以避免资源泄漏
        return 1;
    }

    // ... 执行其他数据库操作 ...

    // 关闭连接
    mysql_close(conn);

    return 0;
}

在这个示例中,我们使用 mysql_real_connect() 函数尝试连接到 MySQL 服务器。如果连接失败,我们使用 mysql_error() 函数获取并打印错误信息。

注意事项

  1. 线程安全性mysql_error() 函数不是线程安全的。如果你在多线程环境中使用 MySQL C API,每个线程都应该有自己的 MYSQL 结构实例,并且应该使用与该线程关联的 MYSQL 指针来调用 mysql_error()

  2. 错误状态清除:当成功调用某些 MySQL C API 函数(如 mysql_real_connect()mysql_query())后,之前的错误状态会被清除。因此,你应该在调用这些函数后立即检查错误,并在需要时保存或处理错误信息。

  3. 错误处理:在调用可能会失败的 MySQL C API 函数后,总是检查返回值并适当使用 mysql_error() 来获取和处理错误信息是一个好习惯。这有助于你更好地理解代码中可能发生的问题,并据此进行调试和修复。



mysql_errno

mysql_errno() 是 MySQL C API 中的一个函数,它用于检索与指定 MySQL 连接关联的最新错误的错误编号。这个错误编号通常与特定的错误消息相关联,可以通过 mysql_error() 函数获得该错误消息。了解错误编号有助于程序员更精确地识别和处理不同类型的数据库错误。

函数原型

在 MySQL 的头文件中,mysql_errno() 函数的原型通常如下所示:

unsigned int mysql_errno(MYSQL *mysql);

参数

  • MYSQL *mysql: 指向一个 MYSQL 结构的指针,该结构表示一个与 MySQL 服务器的连接。这个指针是通过之前的 mysql_init()mysql_real_connect() 调用获得的。

返回值

  • 返回一个无符号整数,代表与指定 MySQL 连接相关联的最新错误的错误编号。如果自上次成功调用 MySQL 函数以来没有出现错误,则返回 0。

错误编号

错误编号是一个整数值,它与特定的错误条件相对应。你可以在 MySQL 的官方文档中查找错误编号列表及其描述,或者使用 perror() 函数(标准 C 库提供)来获取可能的系统级错误消息。

使用示例

下面是一个使用 mysql_errno() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;

    // 初始化 MYSQL 结构
    conn = mysql_init(NULL);
    if (conn == NULL) {
        fprintf(stderr, "mysql_init() failed\n");
        return 1;
    }

    // 连接到 MySQL 服务器
    if (mysql_real_connect(conn, "host", "user", "password", "database", 0, NULL, 0) == NULL) {
        fprintf(stderr, "Connection error: %u: %s\n", mysql_errno(conn), mysql_error(conn));
        mysql_close(conn);
        return 1;
    }

    // ... 执行其他数据库操作 ...

    // 关闭连接
    mysql_close(conn);

    return 0;
}

在这个示例中,我们尝试连接到 MySQL 服务器,并在连接失败时使用 mysql_errno()mysql_error() 来打印错误编号和相应的错误消息。

注意事项

  1. 线程安全性mysql_errno() 函数与 mysql_error() 一样,也不是线程安全的。在多线程环境中使用时,应该为每个线程提供单独的 MYSQL 结构,并使用与当前线程相关联的 MYSQL 指针调用这些函数。

  2. 错误处理:结合使用 mysql_errno()mysql_error() 可以提供有关最近发生的错误的详细信息。在处理 MySQL 错误时,建议总是记录错误编号和错误消息,以便于问题的调试和跟踪。

  3. 错误码的有效期:与 mysql_error() 提供的错误消息不同,错误编号不会因后续的 MySQL 操作而自动清除。然而,为了代码的清晰和准确性,最好在检测到错误后立即处理它。



mysql_real_escape_string

mysql_real_escape_string() 是 MySQL C API 中的一个函数,用于转义 SQL 查询中可能包含的特殊字符,从而防止 SQL 注入攻击。这个函数对于确保应用程序的安全性至关重要,因为它可以帮助开发者避免由于用户输入不当而导致的潜在安全漏洞。

函数原型

在 MySQL 的头文件中,mysql_real_escape_string() 函数的原型通常如下所示:

unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length);

参数

  • MYSQL *mysql: 指向一个 MYSQL 结构的指针,该结构表示一个与 MySQL 服务器的连接。
  • char *to: 指向将要存储转义后字符串的目标缓冲区的指针。
  • const char *from: 指向要转义的原始字符串的指针。
  • unsigned long length: 指定 from 字符串的最大长度。

返回值

  • 返回转义后字符串的长度。如果 to 缓冲区太小,无法容纳完整的转义字符串(包括终止的空字符),则函数将返回所需的长度,但不会写入终止的空字符。

使用示例

下面是一个使用 mysql_real_escape_string() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>
#include <string.h>

int main() {
    MYSQL *conn;
    char query[1024];
    char user_input[] = "John's car"; // 用户输入,可能包含特殊字符
    char escaped_input[2 * sizeof(user_input)]; // 分配足够的空间以存储转义后的字符串
    unsigned long escaped_length;

    // 初始化连接等(省略)

    // 转义用户输入
    escaped_length = mysql_real_escape_string(conn, escaped_input, user_input, sizeof(user_input) - 1);

    // 检查转义是否成功
    if (escaped_length == (unsigned long)-1) {
        fprintf(stderr, "mysql_real_escape_string() failed\n");
        // 错误处理(省略)
        return 1;
    }

    // 构造 SQL 查询
    snprintf(query, sizeof(query), "INSERT INTO cars (name) VALUES ('%s')", escaped_input);

    // 执行查询(省略)

    // 清理和关闭连接(省略)

    return 0;
}

注意事项

  1. 缓冲区大小to 缓冲区必须足够大,以容纳转义后的字符串及其终止的空字符。在最坏的情况下,每个字符都可能被转义(例如,每个字符前面都加上一个反斜杠),因此通常需要为 to 缓冲区分配至少与 from 字符串等长的空间的两倍。

  2. 连接状态mysql_real_escape_string() 需要一个有效的 MYSQL 连接指针。如果连接尚未建立或已关闭,此函数将无法正确工作。

  3. 错误处理:如果函数返回 (unsigned long)-1,则表示出现了错误。这通常是由于提供了无效的 MYSQL 指针或缓冲区太小而无法容纳完整的转义字符串。

  4. 已弃用:值得注意的是,随着 MySQL Connector/C 的更新,mysql_real_escape_string() 可能已被标记为弃用,并建议使用更现代、更安全的方法来处理 SQL 查询中的特殊字符,如使用预处理语句(prepared statements)。因此,在编写新代码或更新现有代码时,请检查最新的 MySQL 文档以获取最佳实践。



mysql_num_rows

mysql_num_rows() 是 MySQL C API 中的一个函数,用于检索结果集中的行数。当你执行一个 SELECT 查询或其他返回结果集的查询时,可以使用此函数来确定结果集中有多少行。

函数原型

在 MySQL 的头文件中,mysql_num_rows() 函数的原型通常如下所示:

my_ulonglong mysql_num_rows(MYSQL_RES *result);

参数

  • MYSQL_RES *result: 指向 MYSQL_RES 结构的指针,该结构包含了一个从 MySQL 服务器检索到的结果集。这通常是通过 mysql_query()mysql_real_query() 函数执行查询后,再使用 mysql_store_result()mysql_use_result() 获得的。

返回值

  • 返回一个无符号长长整型(my_ulonglong),表示结果集中的行数。如果结果集无效或函数调用失败,则返回 (my_ulonglong) -1

使用示例

下面是一个使用 mysql_num_rows() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;
    my_ulonglong num_rows;
    int query_result;

    // 初始化连接等(省略)

    // 执行查询
    query_result = mysql_query(conn, "SELECT * FROM mytable");
    if (query_result) {
        fprintf(stderr, "Query failed: %s\n", mysql_error(conn));
        // 错误处理(省略)
        return 1;
    }

    // 获取结果集
    res = mysql_store_result(conn);
    if (res == NULL) {
        fprintf(stderr, "Failed to store result: %s\n", mysql_error(conn));
        // 错误处理(省略)
        return 1;
    }

    // 获取结果集中的行数
    num_rows = mysql_num_rows(res);
    printf("Number of rows: %llu\n", num_rows);

    // 遍历结果集(可选)
    while ((row = mysql_fetch_row(res)) != NULL) {
        // 处理每一行数据(省略)
    }

    // 释放结果集
    mysql_free_result(res);

    // 关闭连接(省略)

    return 0;
}

注意事项

  1. 结果集有效性mysql_num_rows() 只能用于有效的结果集。如果传递给它的 MYSQL_RES 指针是无效的(例如,因为结果集已经被释放或从未被正确初始化),则函数的行为是未定义的。

  2. 未缓存的结果集:如果你使用 mysql_use_result() 而不是 mysql_store_result() 来获取结果集,那么 mysql_num_rows() 可能无法正确工作,因为 mysql_use_result() 返回一个未缓存的结果集,它可能不知道结果集中的确切行数,直到所有行都被检索。在这种情况下,最好使用 mysql_store_result() 或通过其他方式(如执行 SELECT COUNT(*) 查询)来确定行数。

  3. 错误处理:如果 mysql_num_rows() 返回 (my_ulonglong) -1,则表示出现了错误。你应该检查你的 MYSQL_RES 指针是否有效,并确保在调用 mysql_num_rows() 之前已经成功执行了查询并获取了结果集。

  4. 内存管理:不要忘记在使用完结果集后调用 mysql_free_result() 来释放它,以避免内存泄漏。同样地,在完成与 MySQL 服务器的交互后,应该关闭连接以释放所有相关资源。



mysql_num_fields

mysql_num_fields() 是 MySQL C API 中的一个函数,它用于获取结果集中的字段(列)数量。当你执行一个 SELECT 查询并得到一个结果集时,这个函数可以帮助你确定每个记录中有多少个字段。

函数原型

在 MySQL 的头文件中,mysql_num_fields() 函数的原型通常如下所示:

unsigned int mysql_num_fields(MYSQL_RES *result);

参数

  • MYSQL_RES *result: 指向 MYSQL_RES 结构的指针,该结构包含了一个从 MySQL 服务器检索到的结果集。这通常是通过执行查询后,使用 mysql_store_result()mysql_use_result() 函数获得的。

返回值

  • 返回一个无符号整数(unsigned int),表示结果集中的字段数量。如果结果集无效或函数调用失败,则返回值未定义。

使用示例

下面是一个使用 mysql_num_fields() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;
    MYSQL_RES *res;
    unsigned int num_fields;
    int query_result;

    // 初始化连接(省略)

    // 执行查询
    query_result = mysql_query(conn, "SELECT id, name, age FROM users");
    if (query_result) {
        fprintf(stderr, "Query failed: %s\n", mysql_error(conn));
        // 错误处理(省略)
        return 1;
    }

    // 获取结果集
    res = mysql_store_result(conn);
    if (res == NULL) {
        fprintf(stderr, "Failed to store result: %s\n", mysql_error(conn));
        // 错误处理(省略)
        return 1;
    }

    // 获取结果集中的字段数量
    num_fields = mysql_num_fields(res);
    printf("Number of fields: %u\n", num_fields);

    // 释放结果集
    mysql_free_result(res);

    // 关闭连接(省略)

    return 0;
}

在这个示例中,我们执行了一个查询来选择 users 表中的 idnameage 字段。然后,我们使用 mysql_num_fields() 函数来确定结果集中有多少个字段,并打印出来。

注意事项

  1. 结果集有效性mysql_num_fields() 只能用于有效的结果集。如果传递给它的 MYSQL_RES 指针是无效的(例如,因为结果集已经被释放或从未被正确初始化),则函数的行为是未定义的。

  2. 错误处理:如果 mysql_num_fields() 返回一个意料之外的值(例如,0 或一个非常大的数),那么可能是因为结果集无效或发生了其他错误。你应该检查 MYSQL_RES 指针是否有效,并确保在调用 mysql_num_fields() 之前已经成功执行了查询并获取了结果集。

  3. 内存管理:不要忘记在使用完结果集后调用 mysql_free_result() 来释放它,以避免内存泄漏。即使你没有遍历整个结果集,也应该释放它以防止资源泄露。

  4. 线程安全:如果你的应用程序是多线程的,并且多个线程可能同时调用 MySQL C API 函数,你需要确保每个线程都有自己的 MYSQLMYSQL_RES 结构实例,或者使用适当的同步机制来避免竞争条件。



mysql_field_count

mysql_field_count() 是 MySQL C API 中的一个函数,用于获取最近查询的结果集中的字段(列)数量。这个函数在你执行了像 SELECT 这样的查询后特别有用,因为它可以帮助你确定查询结果中有多少列。

函数原型

在 MySQL 的头文件中,mysql_field_count() 函数的原型通常如下所示:

unsigned int mysql_field_count(MYSQL *mysql);

参数

  • MYSQL *mysql: 指向 MYSQL 结构的指针,该结构代表了与 MySQL 服务器的连接。

返回值

  • 返回一个无符号整数(unsigned int),表示最近查询结果集中的字段数量。如果最近执行的查询没有返回结果集(例如,INSERTUPDATEDELETE),或者连接无效,则返回值可能是未定义的。

使用示例

下面是一个使用 mysql_field_count() 函数的简单示例:

#include <mysql/mysql.h>
#include <stdio.h>

int main() {
    MYSQL *conn;
    unsigned int num_fields;
    int query_result;

    // 初始化连接(省略)

    // 执行查询
    query_result = mysql_query(conn, "SELECT id, name, age FROM users");
    if (query_result) {
        fprintf(stderr, "Query failed: %s\n", mysql_error(conn));
        // 错误处理(省略)
        return 1;
    }

    // 获取结果集中的字段数量
    num_fields = mysql_field_count(conn);
    printf("Number of fields: %u\n", num_fields);

    // ... 这里可以处理结果集 ...

    // 关闭连接(省略)

    return 0;
}

在这个示例中,我们执行了一个 SELECT 查询来选择 users 表中的 idnameage 字段。然后,我们使用 mysql_field_count() 函数来确定查询结果中有多少个字段,并打印出来。

注意事项

  1. 连接有效性mysql_field_count() 需要一个有效的 MYSQL 连接指针。如果连接无效或未初始化,函数的行为是未定义的。

  2. 查询类型:这个函数通常用于 SELECT 查询之后,因为它返回的是结果集中的字段数量。对于不返回结果集的查询(如 INSERTUPDATEDELETE),mysql_field_count() 的返回值可能是不确定的。

  3. 错误处理:如果 mysql_field_count() 返回一个意料之外的值(例如,0 或一个非常大的数),那么可能是因为连接无效或发生了其他错误。你应该检查 MYSQL 指针是否有效,并确保在调用 mysql_field_count() 之前已经成功执行了查询。

  4. mysql_num_fields 的区别mysql_field_count()mysql_num_fields() 都可以用来获取字段数量,但它们的用法有所不同。mysql_num_fields() 需要一个 MYSQL_RES 指针作为参数,这个指针通常是通过 mysql_store_result()mysql_use_result() 获得的。而 mysql_field_count() 则使用 MYSQL 指针,它返回的是最近一次查询的字段数量,不需要显式获取结果集。因此,在处理结果集之前或之后使用 mysql_field_count() 可能是有用的。然而,在处理结果集时,通常更推荐使用 mysql_num_fields(),因为它直接关联到特定的结果集。


posted @   guanyubo  阅读(227)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示