MySQL 9.0 C API 开发者指南  /  C API 预处理语句接口  /  C API 预处理语句接口概述

6.1 C API 预处理语句接口概述

要准备和执行语句,应用程序需要遵循以下步骤

  1. 使用 mysql_stmt_init() 创建一个预处理语句句柄。要准备服务器上的语句,请调用 mysql_stmt_prepare() 并传递一个包含 SQL 语句的字符串。

  2. 使用 mysql_stmt_bind_param()mysql_stmt_bind_named_param() 设置任何参数的值。必须设置所有参数。否则,语句执行将返回错误或产生意外结果。

    如果有要发送的大文本或二进制数据值,可以使用 mysql_stmt_send_long_data() 将它们分块发送到服务器。

  3. 调用 mysql_stmt_execute() 来执行语句。

  4. 如果该语句是 SELECT 或任何其他产生结果集的语句,如果需要获取结果集元数据,请调用 mysql_stmt_result_metadata()。此元数据本身采用 MYSQL_RES 结果集的形式,尽管它与包含查询返回的行分开。元数据结果集指示结果中的列数,并包含有关每一列的信息。

  5. 如果该语句产生结果集,请通过调用 mysql_stmt_bind_result() 绑定用于检索行值的数据缓冲区。

  6. 通过重复调用 mysql_stmt_fetch() 将数据逐行提取到缓冲区中,直到找不到更多行为止。

  7. 根据需要重复步骤 3 到 6。您可以通过更改通过 mysql_stmt_bind_param()mysql_stmt_bind_named_param() 提供的相应缓冲区中的参数值来重复 mysql_stmt_execute() 以重新执行该语句。

  8. 语句执行完成后,使用 mysql_stmt_close() 关闭语句句柄,以便释放与其关联的所有资源。此时,该句柄将变为无效,不应再使用。

  9. 如果您通过调用 mysql_stmt_result_metadata() 获得了 SELECT 语句的结果集元数据,则还应使用 mysql_free_result() 释放该元数据。

当调用 mysql_stmt_prepare() 时,MySQL 客户端/服务器协议执行以下操作

  • 服务器解析语句并通过分配语句 ID 将确认状态发送回客户端。如果它是一个面向结果集的语句,它还会发送参数总数、列数及其元数据。在此调用期间,服务器会检查语句的所有语法和语义。

  • 客户端将此语句 ID 用于后续操作,以便服务器可以从其语句池中识别该语句。

当调用 mysql_stmt_execute() 时,MySQL 客户端/服务器协议执行以下操作

  • 客户端使用语句句柄并将参数数据发送到服务器。

  • 服务器使用客户端提供的 ID 标识语句,将参数标记替换为新提供的数据,然后执行该语句。如果该语句产生结果集,则服务器会将数据发送回客户端。否则,它会发送确认状态以及更改、删除或插入的行数。

当调用 mysql_stmt_fetch() 时,MySQL 客户端/服务器协议执行以下操作

  • 客户端从结果集的当前行读取数据,并通过执行必要的转换将其放入应用程序数据缓冲区中。如果应用程序缓冲区类型与服务器返回的字段类型相同,则转换很简单。

如果发生错误,可以使用 mysql_stmt_errno()mysql_stmt_error()mysql_stmt_sqlstate() 分别获取语句错误号、错误消息和 SQLSTATE 代码。

预处理语句日志记录

对于使用 mysql_stmt_prepare()mysql_stmt_execute() C API 函数执行的预处理语句,服务器会将 PrepareExecute 行写入常规查询日志,以便您可以知道语句何时准备和执行。

假设您准备并执行以下语句

  1. 调用 mysql_stmt_prepare() 来准备语句字符串 "SELECT ?"

  2. 调用 mysql_stmt_bind_param()mysql_stmt_bind_named_param() 将值 3 绑定到预处理语句中的参数。

  3. 调用 mysql_stmt_execute() 来执行预处理语句。

作为上述调用的结果,服务器会将以下行写入常规查询日志

Prepare  [1] SELECT ?
Execute  [1] SELECT 3

日志中的每条 PrepareExecute 行都标记有 [N] 语句标识符,以便您可以跟踪正在记录哪个预处理语句。 N 是一个正整数。如果客户端同时有多个预处理语句处于活动状态,则 N 可能大于 1。每条 Execute 行都显示了用数据值替换 ? 参数后的预处理语句。