文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  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的值确定。

  • 如果参数是属于INSERT语句的SELECT列表的直接成员,则参数的派生类型是插入参数的相应列的类型。

  • 如果参数在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

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

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

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

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