PREPARE stmt_name FROM preparable_stmt
该 PREPARE
语句准备一个 SQL 语句,并将其命名为 stmt_name
,以便以后引用该语句。该预备语句将使用 EXECUTE
执行,并使用 DEALLOCATE PREPARE
释放。有关示例,请参阅 第 15.5 节,“预备语句”。
语句名称不区分大小写。preparable_stmt
是一个字符串文字或用户变量,包含 SQL 语句的文本。该文本必须表示单个语句,而不是多个语句。在语句中,?
字符可以用作参数标记,以指示在执行语句时将绑定到查询的数据值。这些 ?
字符不应被引号括起来,即使您计划将它们绑定到字符串值。
如果已经存在具有给定名称的预备语句,则在准备新语句之前,它将被隐式释放。这意味着,如果新语句包含错误并且无法准备,错误将被返回,并且没有具有给定名称的语句。
预备语句的作用域是创建它的会话,其中有一些含义:
-
在一个会话中创建的预备语句不可用于其他会话。
-
当会话结束时,无论是正常结束还是异常结束,其预备语句将不再存在。如果启用了自动重新连接,客户端不会收到连接丢失的通知。因此,客户端可能希望禁用自动重新连接。请参阅 自动重新连接控制。
-
在存储程序中创建的预备语句将在程序执行完毕后继续存在,并且可以在程序外部稍后执行。
-
在存储程序上下文中创建的预备语句不能引用存储过程或函数参数或局部变量,因为它们在程序结束时将超出范围,并且在以后执行语句时将不可用。作为解决方法,可以引用用户定义的变量,它们也具有会话作用域;请参阅 第 11.4 节,“用户定义变量”。
预备语句中参数的类型是在首次准备语句时确定的;它将保留该类型,直到 EXECUTE
语句执行该预备语句时(除非语句被重新准备,如本节后面所述)。确定参数类型的规则如下:
-
作为二元算术运算符操作数的参数具有与另一个操作数相同的数据类型。
-
如果二元算术运算符的两个操作数都是参数,则参数的类型将由运算符的上下文决定。
-
如果参数是一元算术运算符的操作数,则参数的类型将由运算符的上下文决定。
-
如果算术运算符没有类型确定上下文,则参与运算的参数的派生类型为
DOUBLE PRECISION
。这可能发生在参数是SELECT
列表的顶级节点时,或者当它是比较运算符的一部分时。 -
作为字符字符串运算符操作数的参数具有与其他操作数相同的派生类型。如果所有操作数都是参数,则派生类型为
VARCHAR
;其排序规则由collation_connection
的值确定。 -
作为时间运算符操作数的参数具有
DATETIME
类型,如果运算符返回DATETIME
,具有TIME
类型,如果运算符返回TIME
,具有DATE
类型,如果运算符返回DATE
。 -
一个二进制比较运算符的操作数参数的派生类型与比较运算符的另一个操作数相同。
-
一个三元比较运算符的操作数参数,如
BETWEEN
,其派生类型与其他操作数的聚合类型相同。 -
如果所有比较运算符的操作数都是参数,则每个参数的派生类型为
VARCHAR
,其排序规则由collation_connection
的值确定。 -
任何
CASE
、COALESCE
、IF
、IFNULL
或NULLIF
的输出操作数参数的派生类型与运算符的其他输出操作数的聚合类型相同。 -
如果所有输出操作数都是参数,或者它们都是
NULL
,则参数的类型由运算符的上下文决定。 -
如果参数是
CASE
、COALESCE()
、IF
或IFNULL
的操作数,并且没有类型确定上下文,则每个参数的派生类型为VARCHAR
,其排序规则由collation_connection
的值确定。 -
如果参数是
SELECT
列表的直接成员,不是INSERT
语句的一部分,则参数的派生类型为VARCHAR
,其排序规则由collation_connection
的值确定。 -
如果参数用于
UPDATE
语句的SET子句或INSERT
语句的ON DUPLICATE KEY UPDATE子句中,则参数的派生类型是更新的对应列的类型。
对于某些实际类型和派生类型的组合,会触发语句的自动重新准备,以确保与之前的 MySQL 版本的兼容性。重新准备不会发生,如果以下任何条件为真:
对于上述情况以外的情况,语句将被重新准备,并使用实际参数类型而不是派生参数类型。
这些规则也适用于在准备语句中引用的用户变量。
在准备语句的后续执行中,对于给定的参数或用户变量使用不同的数据类型将导致语句被重新准备。这可能会导致效率下降,也可能会导致参数(或变量)的实际类型发生变化,从而导致结果不一致。在准备语句的后续执行中,建议使用相同的数据类型来避免这些问题。