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


MySQL 9.0 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_library_init()mysql_init() 也是如此。您必须在生成任何线程之前调用 mysql_library_init(),或者使用互斥锁保护调用,无论您是通过 mysql_library_init() 还是通过 mysql_init() 间接调用。这应该在任何其他客户端库调用之前完成。

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

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

注意

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

在连接处于活动状态时,客户端可以使用 mysql_real_query()mysql_query() 将 SQL 语句发送到服务器。两者的区别在于 mysql_query() 预计查询将指定为以 null 结尾的字符串,而 mysql_real_query() 预计为一个计数字符串。如果字符串包含二进制数据(可能包括空字节),则必须使用 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() 函数提供对错误信息的访问。这些函数返回最近调用的可能成功或失败的函数的错误代码或错误消息,使您可以确定何时发生错误以及错误是什么。