预处理语句

2020-11-20

使用PREPARE将语句用占位符(?)(作为参数标记)拼接;使用EXECUTE执行

对参数值使用带占位符,具有以下好处:

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

语法:

PREPARE语句准备一个SQL语句,并为其分配一个名称stmt_name,以便以后引用该语句

PREPARE stmt_name FROM preparable_stmt

EXECUTE执行准备好的语句

EXECUTE stmt_name [USING @var_name [, @var_name] ...]
  • 如果prepared语句包含任何参数标记,则必须提供一个USING 子句,该子句列出包含要绑定到参数的值的用户变量。参数值只能由用户变量提供,并且USING子句的命名变量必须与语句中参数标记的数量一样多。
  • 您可以多次执行给定的预处理语句,将不同的变量传递给它,或者在每次执行之前将变量设置为不同的值
  • 预处理语句中无法动态拼接表名与字段名,如果拼接要使用concat()拼接sql

取消分配使用PREPARE生成的准备好的语句stmt_name

{DEALLOCATE | DROP} PREPARE stmt_name
  • 取消分配后尝试执行准备好的语句会导致错误。

  • 如果创建了太多准备好的语句,并且DEALLOCATE PREPARE语句或会话结束时未将其释放,则可能会遇到max_prepared_stmt_count系统变量强制执行的上限。

示例:

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 |
+------------+
|         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;

预处理允许的语句:

ALTER TABLE
ALTER USER
ANALYZE TABLE
CACHE INDEX
CALL
CHANGE MASTER
CHECKSUM {TABLE | TABLES}
COMMIT
{CREATE | DROP} INDEX
{CREATE | RENAME | DROP} DATABASE
{CREATE | DROP} TABLE
{CREATE | RENAME | DROP} USER
{CREATE | DROP} VIEW
DELETE
DO
FLUSH {TABLE | TABLES | TABLES WITH READ LOCK | HOSTS | PRIVILEGES
  | LOGS | STATUS | MASTER | SLAVE | DES_KEY_FILE | USER_RESOURCES}
GRANT
INSERT
INSTALL PLUGIN
KILL
LOAD INDEX INTO CACHE
OPTIMIZE TABLE
RENAME TABLE
REPAIR TABLE
REPLACE
RESET {MASTER | SLAVE | QUERY CACHE}
REVOKE
SELECT
SET
SHOW {WARNINGS | ERRORS}
SHOW BINLOG EVENTS
SHOW CREATE {PROCEDURE | FUNCTION | EVENT | TABLE | VIEW}
SHOW {MASTER | BINARY} LOGS
SHOW {MASTER | SLAVE} STATUS
SLAVE {START | STOP}
TRUNCATE TABLE
UNINSTALL PLUGIN
UPDATE
 

 

{/if}