文档首页
MySQL 8.4 C API 开发人员指南
下载本手册
PDF (US Ltr) - 1.4Mb
PDF (A4) - 1.4Mb


MySQL 8.4 C API 开发人员指南  /  C API 基本接口  /  C API 基本接口概述

5.1 C API 基本接口概述

应用程序应使用以下一般概述来通过客户端库与 MySQL 交互。

  1. 通过调用 mysql_library_init() 初始化 MySQL 客户端库。

  2. 通过调用 mysql_init() 初始化连接句柄,并通过调用连接建立函数(例如 mysql_real_connect())连接到服务器。

  3. 发出 SQL 语句并处理其结果。(以下讨论提供了有关如何执行此操作的更多信息。)

  4. 通过调用 mysql_close() 关闭与 MySQL 服务器的连接。

  5. 通过调用 mysql_library_end() 结束对 MySQL 客户端库的使用。

调用 mysql_library_init()mysql_library_end() 的目的是为 MySQL 客户端库提供适当的初始化和最终化。对于与客户端库链接的应用程序,它们提供了改进的内存管理。如果您没有调用 mysql_library_end(),则会保留一块已分配的内存。(这不会增加应用程序使用的内存量,但某些内存泄漏检测器会对此提出警告。)

在非多线程环境中,可以省略对 mysql_library_init() 的调用,因为 mysql_init() 会根据需要自动调用它。但是,mysql_library_init() 在多线程环境中不是线程安全的,因此 mysql_init()(它调用 mysql_library_init())也不是线程安全的。您必须在生成任何线程之前调用 mysql_library_init(),或者使用互斥量来保护调用(无论您是通过 mysql_library_init() 还是通过 mysql_init() 间接调用)。这应在任何其他客户端库调用之前完成。

要连接到服务器,请调用 mysql_init() 初始化连接句柄,然后调用连接建立函数(例如 mysql_real_connect()),并使用该句柄(以及其他信息,如主机名、用户名和密码)。完成连接后,请调用 mysql_close() 终止它。连接句柄关闭后,不要再使用它。

连接后,mysql_real_connect()reconnect 标志(MYSQL 结构的一部分)设置为 0。您可以使用 mysql_options() 中的 MYSQL_OPT_RECONNECT 选项(已弃用)来控制重新连接行为。将标志设置为 1 会导致客户端尝试重新连接到服务器,然后再放弃,前提是由于连接丢失而无法执行语句。

注意

自动重新连接功能(第 3.6.8 节“自动重新连接控制”)已弃用,并将在 MySQL 的未来版本中移除。

在连接处于活动状态时,客户端可以使用 mysql_real_query()mysql_query() 将 SQL 语句发送到服务器。两者之间的区别在于 mysql_query() 预计查询将指定为以 null 结尾的字符串,而 mysql_real_query() 预计将指定为已计数的字符串。如果字符串包含二进制数据(可能包括 null 字节),则必须使用 mysql_real_query()

对于每个非 SELECT 查询(例如 INSERTUPDATEDELETE),您可以通过调用 mysql_affected_rows() 找出更改(影响)了多少行。

对于 SELECT 查询,您会将选定的行检索为结果集。(请注意,某些语句类似于 SELECT,因为它们会返回行。这些语句包括 SHOWDESCRIBEEXPLAIN。将这些语句与 SELECT 语句相同的方式处理。)

客户端有两种方式处理结果集。一种方式是通过调用 mysql_store_result() 一次性检索整个结果集。此函数会从服务器获取查询返回的所有行,并将它们存储在客户端中。第二种方式是客户端通过调用 mysql_use_result() 启动逐行结果集检索。此函数会初始化检索,但不会实际从服务器获取任何行。

在这两种情况下,您都可以通过调用 mysql_fetch_row() 访问行。对于 mysql_store_result()mysql_fetch_row() 会访问先前已从服务器获取的行。对于 mysql_use_result()mysql_fetch_row() 会实际从服务器检索行。有关每行中数据大小的信息,可通过调用 mysql_fetch_lengths() 获取。

完成结果集后,请调用 mysql_free_result() 释放为其使用的内存。

这两种检索机制是互补的。选择最适合每个客户端应用程序的方法。在实践中,客户端倾向于更多地使用 mysql_store_result()

mysql_store_result() 的一个优点是,由于所有行都已获取到客户端,因此您不仅可以顺序访问行,还可以使用 mysql_data_seek()mysql_row_seek() 在结果集中前后移动以更改结果集中的当前行位置。您还可以通过调用 mysql_num_rows() 找出有多少行。另一方面,对于大型结果集,mysql_store_result() 的内存需求可能非常高,您更有可能遇到内存不足的情况。

使用mysql_use_result() 的一个优点是,客户端需要的结果集内存更少,因为它一次只维护一行(由于分配开销更少,mysql_use_result() 速度更快)。缺点是您必须快速处理每一行以避免占用服务器,您无法随机访问结果集中的行(您只能按顺序访问行),并且结果集中的行数在您检索完所有行之前是未知的。此外,您必须检索所有行,即使您在检索过程中发现自己已经找到了要查找的信息。

API 使客户端能够适当地响应语句(仅在需要时检索行),而无需知道语句是否是SELECT。您可以通过在每个mysql_real_query()(或mysql_query())之后调用mysql_store_result() 来实现这一点。如果结果集调用成功,则语句为SELECT,您可以读取行。如果结果集调用失败,请调用mysql_field_count() 来确定是否实际上应该返回结果。如果mysql_field_count() 返回零,则语句没有返回任何数据(表明它是一个INSERTUPDATEDELETE 等),并且预计不会返回行。如果mysql_field_count() 不为零,则语句应该返回行,但没有返回。这表明语句是一个SELECT 失败了。有关如何执行此操作的示例,请参见mysql_field_count() 的说明。

mysql_store_result()mysql_use_result() 都使您可以获取有关构成结果集的字段的信息(字段数、字段名称和类型等)。您可以通过重复调用mysql_fetch_field() 来按顺序访问行内的字段信息,也可以通过调用mysql_fetch_field_direct() 按字段号访问行内的字段信息。当前字段游标位置可以通过调用mysql_field_seek() 来更改。设置字段游标会影响对mysql_fetch_field() 的后续调用。您还可以通过调用mysql_fetch_fields() 来一次获取所有字段的信息。

为了检测和报告错误,MySQL 通过mysql_errno()mysql_error() 函数提供对错误信息的访问。这些函数返回最近调用的可能成功或失败的函数的错误代码或错误消息,使您能够确定何时发生错误以及错误是什么。