PREPAREstmt_nameFROMpreparable_stmt
PREPARE语句会准备一个 SQL 语句并分配一个名称stmt_name,之后可以通过该名称引用该语句。准备好的语句使用EXECUTE来执行,并使用DEALLOCATE PREPARE来释放。有关示例,请参见第 15.5 节,“预处理语句”。The PREPARE statement prepares a
SQL statement and assigns it a name,
stmt_name, by which to refer to the
statement later. The prepared statement is executed with
EXECUTE and released with
DEALLOCATE PREPARE. For examples,
see Section 15.5, “Prepared Statements”.
语句名称不区分大小写。preparable_stmt可以是字符串字面值,也可以是包含 SQL 语句文本的用户变量。文本必须表示单条语句,而不是多条语句。在语句中,?字符可用作参数标记,以指示数据值将在执行语句时绑定到查询的位置。即使打算将其绑定到字符串值,?字符也不应放在引号内。参数标记只能用于数据值的位置,而不能用于 SQL 关键字、标识符等。Statement names are not case-sensitive.
preparable_stmt is either a string
literal or a user variable that contains the text of the SQL
statement. The text must represent a single statement, not
multiple statements. Within the statement, ?
characters can be used as parameter markers to indicate where data
values are to be bound to the query later when you execute it. The
? characters should not be enclosed within
quotation marks, even if you intend to bind them to string values.
Parameter markers can be used only where data values should
appear, not for SQL keywords, identifiers, and so forth.
如果具有给定名称的预处理语句已存在,则在准备新语句之前会隐式释放旧语句。这意味着如果新语句包含错误且无法准备,将返回错误,并且不存在具有给定名称的语句。If a prepared statement with the given name already exists, it is deallocated implicitly before the new statement is prepared. This means that if the new statement contains an error and cannot be prepared, an error is returned and no statement with the given name exists.
预处理语句的作用域为创建它的会话,这有几个含义:The scope of a prepared statement is the session within which it is created, which as several implications:
在一个会话中创建的预处理语句对于其他会话不可用。A prepared statement created in one session is not available to other sessions.
当会话结束时,无论是正常还是异常,其预处理语句均不再存在。如果启用自动重连,客户端不会收到连接丢失的通知。因此,客户端可能希望禁用自动重连。参见自动重连控制。When a session ends, whether normally or abnormally, its prepared statements no longer exist. If auto-reconnect is enabled, the client is not notified that the connection was lost. For this reason, clients may wish to disable auto-reconnect. See Automatic Reconnection Control.
在存储程序中创建的预处理语句在程序执行完成后仍然存在,并可以在程序外部执行。A prepared statement created within a stored program continues to exist after the program finishes executing and can be executed outside the program later.
在存储程序上下文中编写的语句不能引用存储过程或函数参数或本地变量,因为程序结束时这些参数会超出作用域,且如果该语句在程序外执行时将无法使用。作为一种变通方法,可以参考用户自定义变量,它们也有会话作用域;参见 第 11.4 节,“用户定义变量”。A statement prepared in stored program context cannot refer to stored procedure or function parameters or local variables because they go out of scope when the program ends and would be unavailable were the statement to be executed later outside the program. As a workaround, refer instead to user-defined variables, which also have session scope; see Section 11.4, “User-Defined Variables”.
预备语句中使用的参数类型是在该语句首次准备时确定的;当 EXECUTE 用于该预备语句时,则保持该类型(除非语句被重新准备,如本节后文所述)。确定参数类型的规则如下:The type of a parameter used in a prepared statement is determined
when the statement is first prepared; it retains this type
whenever EXECUTE is invoked for
this prepared statement (unless the statement is reprepared, as
explained later in this section). Rules for determining a
parameter's type are listed here:
作为二元算术算子操作数的参数与另一个操作数具有相同的数据类型。A parameter which is an operand of a binary arithmetic operator has the same data type as the other operand.
如果一个二元算术算子的两个操作数都是参数,则参数的类型由该运算符的上下文决定。If both operands of a binary arithmetic operator are parameters, the type of the parameters is decided by the context of the operator.
如果参数是一元算术算子的操作数,则参数的类型由该运算符的上下文决定。If a parameter is the operand of a unary arithmetic operator, the parameter's type is decided by the context of the operator.
如果算术算子没有类型决定上下文,任何相关参数的派生类型为
DOUBLE PRECISION例如,当参数是SELECTlist“,或者它是比较运算符的一部分时,就会发生这种情况。If an arithmetic operator has no type-determining context, the derived type for any parameters involved isDOUBLE PRECISION. This can happen, for example, when the parameter is a top-level node in aSELECTlist, or when it is part of a comparison operator.作为字符字符串操作符的参数与其他操作数的聚合类型具有相同的派生类型。如果运算符的所有操作数都是参数,派生类型为
VARCHAR其排序由collation_connection。A parameter which is an operand of a character string operator has the same derived type as the aggregated type of the other operands. If all operands of the operator are parameters, the derived type isVARCHAR; its collation is determined by the value ofcollation_connection.参数作为时间运算符的操作数类型为
DATETIME如果操作符返回DATETIMETIME如果运算符返回TIME且DATE,如果操作员返回DATEA parameter which is an operand of a temporal operator has typeDATETIMEif the operator returns aDATETIME,TIMEif the operator returns aTIME, andDATEif the operator returns aDATE.作为二元比较算子操作数的参数与比较操作子的另一个操作数具有相同的派生类型。A parameter which is an operand of a binary comparison operator has the same derived type as the other operand of the comparison.
作为三元比较算子操作数的参数,如
BETWEEN)具有与其他操作数聚合类型相同的派生类型。A parameter that is an operand of a ternary comparison operator such asBETWEENhas the same derived type as the aggregated type of the other operands.如果比较算子的所有操作数都是参数,每个操作数的派生类型为
VARCHAR其排序由collation_connection。If all operands of a comparison operator are parameters, the derived type for each of them isVARCHAR, with collation determined by the value ofcollation_connection.参数是任意一个输出操作数的参数
CASE,COALESCE,IFIFNULL,或NULLIF的派生类型与运算符其他输出操作数的聚合类型相同。A parameter that is an output operand of any ofCASE,COALESCE,IF,IFNULL, orNULLIFhas the same derived type as the aggregated type of the operator's other output operands.如果
CASECOALESCE,IFIFNULL或者NULLIF是参数,或者它们都是NULL参数的类型由操作符的上下文决定。If all output operands of any ofCASE,COALESCE,IF,IFNULL, orNULLIFare parameters, or they are allNULL, the type of the parameter is decided by the context of the operator.如果参数是
CASE的操作数,COALESCE()IF或IFNULL,且没有类型决定上下文,每个参数的派生类型为VARCHAR),其对照由collation_connection。If the parameter is an operand of any ofCASE,COALESCE(),IF, orIFNULL, and has no type-determining context, the derived type for each of the parameters involved isVARCHAR, and its collation is determined by the value ofcollation_connection.参数是
CAST()的操作数,其类型与CAST()A parameter which is the operand of aCAST()has the same type as specified by theCAST().如果参数是
SELECT列表,且不属于INSERT语句,该参数的派生类型为VARCHAR其排序值由collation_connection。If a parameter is an immediate member of aSELECTlist that is not part of anINSERTstatement, the derived type of the parameter isVARCHAR, and its collation is determined by the value ofcollation_connection.如果参数是
SELECT,该列表属于INSERT语句,那么该参数的派生类型就是插入该参数的对应列的类型。If a parameter is an immediate member of aSELECTlist that is part of anINSERTstatement, the derived type of the parameter is the type of the corresponding column into which the parameter is inserted.如果一个参数被用作
UPDATE语句的SET子句或INSERT语句的ON DUPLICATE KEY UPDATE子句中的赋值源,则该参数的派生类型为由SET或ON DUPLICATE KEY UPDATE子句更新的相应列的类型。If a parameter is used as source for an assignment in aSETclause of anUPDATEstatement or in theON DUPLICATE KEY UPDATEclause of anINSERTstatement, the derived type of the parameter is the type of the corresponding column which is updated by theSETorON DUPLICATE KEY UPDATEclause.如果参数是函数的参数,则派生类型取决于函数的返回类型。If a parameter is an argument of a function, the derived type depends on the function's return type.
对于某些实际类型和派生类型的组合,会触发语句的自动重新准备,以确保与早期版本的 MySQL 更兼容。如果满足以下任一条件,则不会重新准备:For some combinations of actual type and derived type, an automatic repreparation of the statement is triggered, to ensure closer compatibility with previous versions of MySQL. Repreparation does not occur if any of the following conditions are true:
使用
NULL作为实际参数值。NULLis used as the actual parameter value.参数是
CAST()的操作数。(在这种情况下,会尝试将其转换为派生类型,如果转换失败则抛出异常。)A parameter is an operand of aCAST(). (Instead, a cast to the derived type is attempted, and an exception raised if the cast fails.)参数是字符串。(在这种情况下,会执行隐式
CAST(? AS derived_type)。)A parameter is a string. (In this case, an implicitCAST(? ASis performed.)derived_type)参数的派生类型和实际类型都是
INTEGER且符号相同。The derived type and actual type of the parameter are bothINTEGERand have the same sign.参数的派生类型是
DECIMAL,实际类型为DECIMAL或INTEGER。The parameter's derived type isDECIMALand its actual type is eitherDECIMALorINTEGER.派生类型是
DOUBLE,实际类型是任何数值类型。The derived type isDOUBLEand the actual type is any numeric type.派生类型和实际类型都是字符串类型。Both the derived type and the actual type are string types.
如果派生类型是时间类型且实际类型也是时间类型。例外:派生类型是
TIME而实际类型不是TIME;派生类型是DATE而实际类型不是DATE。If the derived type is temporal and the actual type is temporal. Exceptions: The derived type isTIMEand the actual type is notTIME; the derived type isDATEand the actual type is notDATE.派生类型是时间类型而实际类型是数值类型。The derived type is temporal and the actual type is numeric.
对于除上述情况之外的其他情况,语句将被重新准备,并使用实际参数类型代替派生参数类型。For cases other than those just listed, the statement is reprepared and the actual parameter types are used instead of the derived parameter types.
这些规则同样适用于在预处理语句中引用的用户变量。These rules also apply to a user variable referenced in a prepared statement.
在预处理语句的第一次执行之后,如果对给定参数或用户变量使用不同的数据类型,将导致该语句被重新预处理。这效率较低;同时也可能导致参数(或变量)的实际类型发生变化,从而使预处理语句的后续执行结果不一致。因此,建议在重新执行预处理语句时对给定参数使用相同的数据类型。Using a different data type for a given parameter or user variable within a prepared statement for executions of the statement subsequent to the first execution causes the statement to be reprepared. This is less efficient; it may also lead to the parameter's (or variable's) actual type to vary, and thus for results to be inconsistent, with subsequent executions of the prepared statement. For these reasons, it is advisable to use the same data type for a given parameter when re-executing a prepared statement.