6.2.2 C API 预处理语句类型转换

预处理语句使用客户端上的 C 语言变量与服务器端上的 SQL 值进行数据传输。如果客户端上的 C 变量类型与服务器端上的对应 SQL 值类型不匹配,MySQL 会在两个方向上执行隐式类型转换。

MySQL 了解服务器端上的 SQL 值的类型代码。 MYSQL_BIND 结构中的 buffer_type 值表示保存客户端上值的 C 变量的类型代码。这两个代码一起告诉 MySQL 必须执行哪些转换(如果有)。以下是一些示例

  • 如果您使用 MYSQL_TYPE_LONGint 变量将整数类型的值传递给服务器,该值将存储在 FLOAT 列中,MySQL 会在存储之前将该值转换为浮点数格式。

  • 如果您获取 SQL MEDIUMINT 列值,但指定 buffer_type 值为 MYSQL_TYPE_LONGLONG,并使用类型为 long long int 的 C 变量作为目标缓冲区,MySQL 会将 MEDIUMINT 值(需要少于 8 字节)转换为 long long int(一个 8 字节变量)以进行存储。

  • 如果您将数值列的值 255 获取到 char[4] 字符数组中,并指定 buffer_type 值为 MYSQL_TYPE_STRING,则数组中的结果值为 4 字节字符串 '255\0'

  • MySQL 以原始服务器端值的字符串形式返回 DECIMAL 值,这就是为什么相应的 C 类型为 char[]。例如,12.345 将以 '12.345' 的形式返回给客户端。如果您指定 MYSQL_TYPE_NEWDECIMAL 并将字符串缓冲区绑定到 MYSQL_BIND 结构,则 mysql_stmt_fetch() 将值存储在缓冲区中,作为字符串,不进行转换。如果您改为指定数值变量和类型代码,则 mysql_stmt_fetch() 会将字符串格式的 DECIMAL 值转换为数值形式。

  • 对于 MYSQL_TYPE_BIT 类型代码, BIT 值将返回到字符串缓冲区中,这就是为什么相应的 C 类型为 char[]。该值表示位字符串,需要在客户端进行解释。为了以更易于处理的类型返回该值,您可以使用以下两种类型的表达式之一强制将该值转换为整数

    SELECT bit_col + 0 FROM t
    SELECT CAST(bit_col AS UNSIGNED) FROM t

    要检索该值,请绑定一个足够大的整数变量来保存该值,并指定相应的整数类型代码。

在将变量绑定到用于获取列值的 MYSQL_BIND 结构之前,您可以检查结果集每列的类型代码。如果您想确定使用哪些变量类型最适合避免类型转换,这可能是有益的。要获取类型代码,请在使用 mysql_stmt_execute() 执行语句后调用 mysql_stmt_result_metadata()。元数据提供对结果集类型代码的访问,如 第 6.4.24 节,“mysql_stmt_result_metadata()”第 5.2 节,“C API 基本数据结构” 中所述。

要确定从服务器返回的结果集中的输出字符串值是否包含二进制数据或非二进制数据,请检查结果集元数据的 charsetnr 值是否为 63(请参见 第 5.2 节,“C API 基本数据结构”)。如果是,则字符集为 binary,表示二进制数据而不是非二进制数据。这使您可以区分 BINARYCHARVARBINARYVARCHAR,以及 BLOB 类型和 TEXT 类型。

如果您强制 MYSQL_FIELD 列元数据结构的 max_length 成员被设置(通过调用 mysql_stmt_attr_set()),请注意,结果集的 max_length 值表示结果值的字符串形式的长度,而不是二进制形式的长度。也就是说,max_length 不一定对应于使用预处理语句的二进制协议获取值的缓冲区大小。根据您获取值的变量的类型选择缓冲区的大小。例如,包含值 -128 的 TINYINT 列可能具有 max_length 值为 4。但任何 TINYINT 值的二进制表示只需要 1 字节来存储,因此您可以提供一个 signed char 变量来存储该值,并设置 is_unsigned 以指示值是有符号的。

对预处理语句引用的表或视图进行的元数据更改会被检测到,并导致在下次执行语句时自动重新准备该语句。有关更多信息,请参见 预处理语句和存储程序的缓存