文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  PREPARE 语句

15.5.1 PREPARE 语句

PREPARE stmt_name FROM preparable_stmt

PREPARE 语句预处理一个 SQL 语句并为其分配一个名称,stmt_name,以便稍后引用该语句。预处理语句使用 EXECUTE 执行,并使用 DEALLOCATE PREPARE 释放。有关示例,请参见 第 15.5 节,“预处理语句”

语句名称不区分大小写。preparable_stmt 是一个字符串字面量或包含 SQL 语句文本的用户变量。文本必须表示单个语句,而不是多个语句。在语句中,? 字符可以用作参数标记,以指示在以后执行查询时将在何处绑定数据值。即使您打算将 ? 字符绑定到字符串值,也不应将其括在引号中。参数标记只能出现在数据值应该出现的地方,而不能用于 SQL 关键字、标识符等。

如果具有给定名称的预处理语句已存在,则在预处理新语句之前,它会被隐式释放。这意味着如果新语句包含错误且无法预处理,则会返回错误,并且不存在具有给定名称的语句。

预处理语句的作用域是创建它的会话,这有几个含义

  • 在一个会话中创建的预处理语句不能被其他会话使用。

  • 当一个会话结束时,无论是正常结束还是异常结束,它的预处理语句都不再存在。如果启用了自动重新连接,则客户端不会收到连接丢失的通知。因此,客户端可能希望禁用自动重新连接。请参阅 自动重新连接控制

  • 在存储程序中创建的预处理语句在程序执行完毕后继续存在,并且可以在程序外部稍后执行。

  • 在存储程序上下文中准备的语句不能引用存储过程或函数参数或局部变量,因为它们在程序结束时超出范围,并且如果在程序外部稍后执行该语句,则将不可用。作为一种解决方法,请改用用户定义的变量,这些变量也具有会话范围;请参阅 第 11.4 节,“用户定义的变量”

在预处理语句中使用的参数类型在首次准备语句时确定;每当为此预处理语句调用 EXECUTE 时,它都会保留此类型(除非重新准备了语句,如本节稍后所述)。确定参数类型的规则如下:

  • 作为二元算术运算符的操作数的参数与另一个操作数具有相同的数据类型。

  • 如果二元算术运算符的两个操作数都是参数,则参数的类型由运算符的上下文决定。

  • 如果参数是一元算术运算符的操作数,则参数的类型由运算符的上下文决定。

  • 如果算术运算符没有类型确定上下文,则涉及的任何参数的派生类型都是 DOUBLE PRECISION。例如,当参数是 SELECT 列表中的顶级节点时,或者当它是比较运算符的一部分时,就会发生这种情况。

  • 作为字符串运算符的操作数的参数与其他操作数的聚合类型具有相同的派生类型。如果运算符的所有操作数都是参数,则派生类型为 VARCHAR;其排序规则由 collation_connection 的值确定。

  • 作为时间运算符的操作数的参数的类型为:如果运算符返回 DATETIME,则为 DATETIME;如果运算符返回 TIME,则为 TIME;如果运算符返回 DATE,则为 DATE

  • 作为二元比较运算符的操作数的参数与比较的另一个操作数具有相同的派生类型。

  • 作为三元比较运算符(例如 BETWEEN)的操作数的参数与其他操作数的聚合类型具有相同的派生类型。

  • 如果比较运算符的所有操作数都是参数,则每个操作数的派生类型都是 VARCHAR,其排序规则由 collation_connection 的值确定。

  • 作为 CASECOALESCEIFIFNULLNULLIF 中任何一个的输出操作数的参数与运算符的其他输出操作数的聚合类型具有相同的派生类型。

  • 如果 CASECOALESCEIFIFNULLNULLIF 中任何一个的所有输出操作数都是参数,或者它们都是 NULL,则参数的类型由运算符的上下文决定。

  • 如果参数是 CASECOALESCE()IFIFNULL 中任何一个的操作数,并且没有类型确定上下文,则涉及的每个参数的派生类型都是 VARCHAR,其排序规则由 collation_connection 的值确定。

  • 作为 CAST() 的操作数的参数与 CAST() 指定的类型相同。

  • 如果参数是 SELECT 列表的直接成员,并且该列表不是 INSERT 语句的一部分,则参数的派生类型为 VARCHAR,其排序规则由 collation_connection 的值确定。

  • 如果参数是 SELECT 列表的直接成员,并且该列表是 INSERT 语句的一部分,则参数的派生类型是插入参数的对应列的类型。

  • 如果参数在 UPDATE 语句的 SET 子句中或在 INSERT 语句的 ON DUPLICATE KEY UPDATE 子句中用作赋值的来源,则参数的派生类型是由 SETON DUPLICATE KEY UPDATE 子句更新的对应列的类型。

  • 如果参数是函数的参数,则派生类型取决于函数的返回类型。

对于实际类型和派生类型的某些组合,会触发语句的自动重新准备,以确保与以前版本的 MySQL 更接近地兼容。如果满足以下任何条件,则不会发生重新准备:

  • NULL 用作实际参数值。

  • 参数是 CAST() 的操作数。(相反,将尝试转换为派生类型,如果转换失败,则会引发异常。)

  • 参数是字符串。(在这种情况下,将执行隐式 CAST(? AS derived_type)。)

  • 参数的派生类型和实际类型都是 INTEGER,并且符号相同。

  • 参数的派生类型为 DECIMAL,其实际类型为 DECIMALINTEGER

  • 派生类型为 DOUBLE,实际类型为任何数字类型。

  • 派生类型和实际类型都是字符串类型。

  • 如果派生类型是时间类型,并且实际类型也是时间类型。例外情况:派生类型为 TIME,实际类型不是 TIME;派生类型为 DATE,实际类型不是 DATE

  • 派生类型是时间类型,实际类型是数字类型。

对于除上面列出的情况以外的其他情况,将重新准备语句,并使用实际参数类型而不是派生参数类型。

这些规则也适用于在预处理语句中引用的用户变量。

在预处理语句中,对给定参数或用户变量使用不同的数据类型会导致在第一次执行后重新准备该语句。效率较低;还可能导致参数(或变量)的实际类型发生变化,从而导致预处理语句后续执行的结果不一致。因此,建议在重新执行预处理语句时对给定参数使用相同的数据类型。