ITPub博客

首页 > 数据库 > > 13.5 被准备SQL语句的语法

13.5 被准备SQL语句的语法

作者:飘絮絮絮丶 时间:2020-05-12 10:21:42 0 删除 编辑

参考官方文档:
dev.mysql.com/doc/refma




MySQL 5.7提供了对服务器端预处理语句的支持。 此支持利用高效的客户端/服务器二进制协议。 使用准备好的语句和占位符来获取参数值具有以下好处:

  • 每次执行时解析语句的开销都较小。 通常情况下,数据库应用程序处理大量几乎相同的语句,只对WHERE查询和删除,SET更新和VALUES等子句中的文字或变量值进行更改。
  • 防止SQL注入攻击。 参数值可以包含未转义的SQL引号和分隔符字符。



--手动软解析




在SQL 脚本中的准备的语句



预备语句的备选SQL接口可用。 这个接口不如通过预先准备好的语句API使用二进制协议那样高效,但不需要编程,因为它可直接在SQL级别使用:

  • 当没有可用的编程接口时,您可以使用它。
  • 您可以从任何可以将SQL语句发送到要执行的服务器的程序中使用它,例如mysql客户端程序。
  • 即使客户端使用旧版本的客户端库,只要连接到运行MySQL 4.1或更高版本的服务器即可使用它。



准备好的语句的SQL语法旨在用于以下情况:

  • 在编写代码之前,测试预准备语句在应用程序中的工作方式
  • 当您无法访问支持它们的编程API时使用预准备语句。
  • 使用预准备语句交互式解决应用程序问题。
  • 创建一个测试用例,用准备好的语句重现问题,以便您可以提交错误报告。





PREPARE,EXECUTE和DEALLOCATE PREPARE语句
预准备语句的SQL语法基于三个SQL语句:

  • PREPARE准备一份执行语句
  • EXECUTE执行一个准备好的语句
  • DEALLOCATE PREPARE发布一个准备好的语句



下面的例子展示了准备计算三角形斜边的两种等价方法,给出了双方的长度。

第一个例子展示了如何通过使用字符串文字来提供语句的文本来创建一个准备好的语句:

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不支持以下为预处理语句:


  • SHOW WARNINGS, SHOW COUNT(*) WARNINGS
  • SHOW ERRORS, SHOW COUNT(*) ERRORS
  • 包含对warning_count或error_count系统变量的任何引用的语句。



其他语句在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/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: Spark SQL 的 Catalyst
请登录后发表评论 登录
全部评论

注册时间:2019-09-09

  • 博文量
    2646
  • 访问量
    42341