首页 > 数据库 > > 13.5 被准备SQL语句的语法
参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
MySQL 5.7提供了对服务器端预处理语句的支持。 此支持利用高效的客户端/服务器二进制协议。 使用准备好的语句和占位符来获取参数值具有以下好处:
--手动软解析
在SQL 脚本中的准备的语句
预备语句的备选SQL接口可用。 这个接口不如通过预先准备好的语句API使用二进制协议那样高效,但不需要编程,因为它可直接在SQL级别使用:
准备好的语句的SQL语法旨在用于以下情况:
PREPARE,EXECUTE和DEALLOCATE PREPARE语句
预准备语句的SQL语法基于三个SQL语句:
下面的例子展示了准备计算三角形斜边的两种等价方法,给出了双方的长度。
第一个例子展示了如何通过使用字符串文字来提供语句的文本来创建一个准备好的语句:
mysql> PREPARE stmt1 FROM'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;
第二个例子是类似的,但将语句的文本作为用户变量提供:
mysql> SET @s ='SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
| 10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;
下面是一个附加示例,演示如何选择要在运行时执行查询的表,方法是将表的名称存储为用户变量:
mysql> USE test;
mysql> CREATE TABLE t1 (a INT NOT NULL);
mysql> INSERT INTO t1 VALUES (4), (8), (11), (32), (80);
mysql> SET @table = 't1';
mysql> SET @s = CONCAT('SELECT * FROM ', @table);
mysql> PREPARE stmt3 FROM @s;
mysql> EXECUTE stmt3;
+----+
| a |
+----+
| 4 |
| 8 |
| 11 |
| 32 |
| 80 |
+----+
mysql> DEALLOCATE PREPARE stmt3;
准备好的声明特定于创建它的会话。 如果您在不取消分配先前准备好的语句的情况下终止会话,则服务器会自动解除分配它。
准备好的声明也是全球会议。 如果您在已存储的例程中创建预准备语句,则在存储的例程结束时不会释放它。
为了防止同时创建的准备语句过多,请设置max_prepared_stmt_count系统变量。 要防止使用预准备语句,请将该值设置为0。
准备好的语句中允许的SQL语法
从MySQL 5.7.2开始,为了遵守声明诊断语句不可预备的SQL标准,MySQL不支持以下为预处理语句:
其他语句在MySQL 5.7中不受支持。
一般来说,SQL准备语句中不允许的语句在存储的程序中也是不允许的。
对准备好的语句引用的表或视图的元数据更改会被检测到,并在下次执行时导致语句自动重新编译。
使用预处理语句时,占位符可用于LIMIT子句的参数。
在与PREPARE和EXECUTE一起使用的准备好的CALL语句中,对于OUT和INOUT参数的占位符支持可以从MySQL 5.7开始。 有关早期版本的示例和解决方法,请参见第13.2.1节“CALL语法”。 无论版本如何,占位符均可用于IN参数。
预处理语句的SQL语法不能以嵌套方式使用。 也就是说,传递给PREPARE的语句本身不能是PREPARE,EXECUTE或DEALLOCATE PREPARE语句。
预处理语句的SQL语法与使用预处理语句API调用截然不同。 例如,不能使用mysql_stmt_prepare()C API函数来准备PREPARE,EXECUTE或DEALLOCATE PREPARE语句。
预编译语句的SQL语法可以在存储过程中使用,但不能在存储函数或触发器中使用。 但是,游标不能用于使用PREPARE和EXECUTE准备并执行的动态语句。 游标创建时检查游标的语句,因此语句不能是动态的。
预准备语句的SQL语法不支持多语句(即,由单个字符串中的多个语句分隔;字符)。
要编写使用CALL SQL语句执行包含预处理语句的存储过程的C程序,必须启用CLIENT_MULTI_RESULTS标志。 这是因为除了过程中执行的语句可能返回的任何结果集外,每个CALL都会返回一个结果来指示调用状态。
在调用mysql_real_connect()时,可以启用CLIENT_MULTI_RESULTS,或者显式地通过传递CLIENT_MULTI_RESULTS标志本身,或者通过传递CLIENT_MULTI_STATEMENTS(它也启用CLIENT_MULTI_RESULTS)来隐式调用。
13.5.1 PREPARE 语法
PREPARE stmt_name FROM preparable_stmt
PREPARE语句准备一条SQL语句并为其指定一个名称stmt_name,稍后通过该名称来引用该语句。 准备好的语句使用EXECUTE执行和DEALLOCATE PREPARE释放。
语句名称不区分大小写。 preparable_stmt是一个字符串文字或包含用户变量的SQL语句文本。 文本必须代表单一语句,而不是多个语句。 在语句中,? 字符可以用作参数标记来指示稍后在执行时将数据值绑定到查询的位置。 这个? 字符不应包含在引号内,即使您打算将它们绑定到字符串值。 参数标记只能用于出现数据值的地方,而不能用于SQL关键字,标识符等等。
如果具有给定名称的准备好的语句已经存在,则在准备新语句之前隐式地释放它。 这意味着如果新语句包含错误并且无法准备,并会返回错误,并且不存在具有给定名称的语句。
准备好的语句的范围是创建它的会话,其中包含以下几个含义:
13.5.2 EXECUTE 语法
EXECUTE stmt_name [USING @var_name [, @var_name] ...]
在使用PREPARE准备语句之后,使用引用准备好的语句名称的EXECUTE语句来执行它。 如果准备的语句包含任何参数标记,则必须提供一个USING子句,其中列出了包含要绑定到参数的值的用户变量。 参数值只能由用户变量提供,并且USING子句必须与语句中参数标记的数目完全相同。
您可以多次执行给定的预处理语句,将不同的变量传递给它,或者在每次执行之前将变量设置为不同的值。
13.5.3 DEALLOCATE 语法
{DEALLOCATE | DROP} PREPARE stmt_name
要取消分配使用PREPARE生成的预备语句,请使用引用准备好的语句名称的DEALLOCATE PREPARE语句。 试图在释放它之后执行预备语句会导致错误。 如果创建的准备语句过多,而且未通过DEALLOCATE PREPARE语句或会话结束释放,则可能会遇到由max_prepared_stmt_count系统变量强制执行的上限。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3167244/ ,如需转载,请注明出处,否则将追究法律责任。