官方参考:https://dev.mysql.com/doc/refman/5.7/en/sql-prepared-statements.html

一、SQL 语句的执行处理

1、即时 SQL

  一条 SQL 在 DB 接收到最终执行完毕返回,大致的过程如下:

  1. 词法和语义解析;

  2. 优化 SQL 语句,制定执行计划;

  3. 执行并返回结果;

  如上,一条 SQL 直接是走流程处理,一次编译,单次运行,此类普通语句被称作 Immediate Statements (即时 SQL)。

2、预处理 SQL

  但是,绝大多数情况下,某需求某一条 SQL 语句可能会被反复调用执行,或者每次执行的时候只有个别的值不同(比如 select 的 where 子句值不同,update 的 set 子句值不同,insert 的 values 值不同)。如果每次都需要经过上面的词法语义解析、语句优化、制定执行计划等,则效率就明显不行了。

  所谓预编译语句就是将此类 SQL 语句中的值用占位符替代,可以视为将 SQL 语句模板化或者说参数化,一般称这类语句叫Prepared Statements。

  预编译语句的优势在于归纳为:一次编译、多次运行,省去了解析优化等过程;此外预编译语句能防止 SQL 注入。

注意:

  虽然可能是通过预处理 SQL 的方式一定程度的提高了效率,但是对于优化而言,最优的执行计划不是光靠 SQL 语句的模板化来实现的,往往还是需要通过具体值来预估出成本代价。

二、Prepared SQL Statement Syntax

  MySQL 官方将 prepare、execute、deallocate 统称为 PREPARE STATEMENT。翻译也就习惯的称其为预处理语句。

  MySQL 预处理语句的支持版本较早,所以我们目前普遍使用的 MySQL 版本都是支持这一语法的。

语法:

# 定义预处理语句

PREPARE stmt_name FROM preparable_stmt;

# 执行预处理语句

EXECUTE stmt_name [USING @var_name [, @var_name] ...];

# 删除(释放)定义

{DEALLOCATE | DROP} PREPARE stmt_name;

1、利用字符串定义预处理 SQL (直角三角形计算)

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';

Query OK, 0 rows affected (0.00 sec)

Statement prepared

mysql> SET @a = 3;

Query OK, 0 rows affected (0.00 sec)

mysql> SET @b = 4;

Query OK, 0 rows affected (0.00 sec)

mysql> EXECUTE stmt1 USING @a, @b;

+------------+

| hypotenuse |

+------------+

|          5 |

+------------+

1 row in set (0.00 sec)

mysql> DEALLOCATE PREPARE stmt1;

Query OK, 0 rows affected (0.00 sec)

2、利用变量定义预处理 SQL (直角三角形计算)

mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';

Query OK, 0 rows affected (0.00 sec)

mysql> PREPARE stmt2 FROM @s;

Query OK, 0 rows affected (0.00 sec)

Statement prepared

mysql> SET @c = 6;

Query OK, 0 rows affected (0.00 sec)

mysql> SET @d = 8;

Query OK, 0 rows affected (0.00 sec)

mysql> EXECUTE stmt2 USING @c, @d;

+------------+

| hypotenuse |

+------------+

|         10 |

+------------+

1 row in set (0.00 sec)

mysql> DEALLOCATE PREPARE stmt2;

Query OK, 0 rows affected (0.00 sec)

3、解决无法传参问题

  我们知道,对于 LIMIT 子句中的值,必须是常量,不得使用变量,也就是说不能使用:SELECT * FROM TABLE LIMIT @skip, @numrows; 如此,就可以是用 PREPARE 语句解决此问题。

mysql> SET @skip = 100; SET @numrows = 3;

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM t1 LIMIT @skip, @numrows;

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@skip, @numrows' at line 1

mysql> PREPARE stmt3 FROM "SELECT * FROM t1 LIMIT ?, ?";

Query OK, 0 rows affected (0.00 sec)

Statement prepared

mysql> EXECUTE stmt3 USING @skip, @numrows;

+-----+--------+

| a   | filler |

+-----+--------+

| 100 | filler |

| 101 | filler |

| 102 | filler |

+-----+--------+

3 rows in set (0.00 sec)

mysql> DEALLOCATE PREPARE stmt3;

Query OK, 0 rows affected (0.00 sec)

  如此一来,结合2中介绍的利用变量定义预处理 SQL 也就基本解决了传参时语法报错问题了,类似的:用变量传参做表名时,MySQL 会把变量名当做表名,这样既不是本意,也会是语法错误,在 SQL Server 的解决办法是利用字符串拼接穿插变量进行传参,再将整条 SQL 语句作为变量,最后是用 sp_executesql 调用该拼接 SQL 执行,而 Prepared SQL Statement 可谓异曲同工之妙。

mysql> SET @table = 't2';

Query OK, 0 rows affected (0.00 sec)

mysql> SET @s = CONCAT('SELECT * FROM ', @table);

Query OK, 0 rows affected (0.00 sec)

mysql> PREPARE stmt4 FROM @s;

Query OK, 0 rows affected (0.00 sec)

Statement prepared

mysql> EXECUTE stmt4;

+------+-------+-------+

| id   | score | grade |

+------+-------+-------+

|    1 |    99 | A     |

|    2 |    81 | B     |

|    3 |    55 | D     |

|    4 |    69 | C     |

+------+-------+-------+

4 rows in set (0.00 sec)

mysql> DROP PREPARE stmt4;

Query OK, 0 rows affected (0.00 sec)

三、预处理 SQL 使用注意点

1、stmt_name 作为 preparable_stmt 的接收者,唯一标识,不区分大小写。

2、preparable_stmt 语句中的 ? 是个占位符,所代表的是一个字符串,不需要将 ? 用引号包含起来。

3、定义一个已存在的 stmt_name ,原有的将被立即释放,类似于变量的重新赋值。

4、PREPARE stmt_name 的作用域是session级

  可以通过 max_prepared_stmt_count 变量来控制全局最大的存储的预处理语句。

mysql> show variables like 'max_prepared%';

+-------------------------+-------+

| Variable_name           | Value |

+-------------------------+-------+

| max_prepared_stmt_count | 16382 |

+-------------------------+-------+

1 row in set (0.00 sec)

  预处理编译 SQL 是占用资源的,所以在使用后注意及时使用 DEALLOCATE PREPARE 释放资源,这是一个好习惯。

MySQL的SQL预处理(Prepared)相关推荐

  1. c mysql prepared_MySQL的SQL预处理(Prepared)

    Prepared SQL Statement:SQL的执行.预编译处理语法.注意点 一.SQL 语句的执行处理 1.即时 SQL 一条 SQL 在 DB 接收到最终执行完毕返回,大致的过程如下: 1. ...

  2. mysql 防注入 php_PHP+mysql防止SQL注入的方法小结

    本文实例讲述了PHP+mysql防止SQL注入的方法.分享给大家供大家参考,具体如下: SQL注入 例:脚本逻辑 $sql = "SELECT * FROM user WHERE useri ...

  3. oracle类型sql转为mysql_Oracle和MySql之间SQL区别(等效转换以及需要注意的问题)...

    >本篇博文是Oracle和MySQL之间的等效SQL转换和不同,目前市面上没有转换两种SQL的工具,小编觉得以后也不一定会有,于是在业余时间整理了一下,如果有什么错误之处请留言告知,小编也是刚 ...

  4. MySQL数据库SQL层级优化

    MySQL数据库SQL层级优化 本篇主涉及MySQL SQL Statements层面的优化. 首先,推荐一个链接为万物之始:http://dev.mysql.com/doc/refman/5.0/e ...

  5. mysql数据库预处理_一种MySQL数据库中间件预处理方法与流程

    本发明属于通信领域,特别涉及一种MySQL数据库中间件预处理方法. (二) 背景技术: 通常来说,MySQL集群和应用程序之间需要通过一个中间件来实现通信.中间件的作用是,对于应用程序来说,不需要关心 ...

  6. mysql执行sql语句按钮_mysql执行sql语句过程

    开发人员基本都知道,我们的数据存在数据库中(目前最多的是mysql和oracle,由于作者更擅长mysql,所以这里默认数据库为mysql),服务器通过sql语句将查询数据的请求传入到mysql数据库 ...

  7. php mysql 防 sql注入_php 防sql注入方法

    php防sql注入的方法:1.使用mysql_real_escape_string方法转义SQL语句中使用的字符串中的特殊字符:2.打开magic_quotes_gpc来防止SQL注入:3.通过自定义 ...

  8. mysql注入实例获取答案_本文实例讲述了MySQL解决SQL注入的另类方法。分享给大家供大家参考,具体如下:问题解读我觉得,这个问题每年带来的成本可以高达数十亿美元了。本文就来谈谈,...

    本文实例讲述了MySQL解决SQL注入的另类方法.分享给大家供大家参考,具体如下: 问题解读 我觉得,这个问题每年带来的成本可以高达数十亿美元了.本文就来谈谈,假定我们有如下 SQL 模板语句: se ...

  9. 雷林鹏分享:MySQL 及 SQL 注入

    MySQL 及 SQL 注入 如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题. 本章节将为大家介绍如何防止SQL注入,并通过脚本来过滤SQL中注入 ...

最新文章

  1. 基于C++的OpenCV常用函数
  2. 绿标2.0隐私权限解读——应用分类及对应权限展示
  3. Java过滤特殊字符的正则表达式
  4. Spring中的常用注解
  5. delphi中move函数的用法
  6. 4,postman和newman的联合使用
  7. php 伪静态 获取当前页面路径_织梦移动适配PHP获取当前页面URL地址方法
  8. php中的递归算法,PHP递归算法(四)
  9. 什么是WEB?如何学习web
  10. C++俄罗斯方块(linux环境)-转 感觉非常好
  11. 18个有用的 .htaccess 文件使用技巧
  12. SQL Server 日期+4位流水号
  13. linux和windows精简版,win7 64/86 超级精简版877MB -三蛋作品
  14. 关于DBSCAN聚类算法
  15. PxCook 高效智能的研发设计工具。点击设计稿即可生成前端代码的智能标注切图软件
  16. 史上最强!PC时代的20位英雄(组图)
  17. 图神经网络(ICML2022)
  18. k8s学习-Secret(创建、使用、更新、删除等)
  19. VS C#-EXE文件如何将ICO图片添加进去
  20. MySQL基础期末考试试题

热门文章

  1. 【报告分享】企鹅智家智慧社区解决方案2019.pdf(附下载链接)
  2. 使用方法_山西硅肥使用方法
  3. php背景色如何填充满,php - 按一定百分比覆盖背景颜色
  4. 将markdown文本转换为微信文章格式的解决方案
  5. C++常见编译问题问题(慢慢积累)
  6. TensorFlow2.0:索引和切片(2)
  7. Docker Jenkins Node(一):初步构建
  8. LeetCode刷题(44)--Remove Duplicates from Sorted Array II
  9. python爬取微博恶评_Python爬取新浪微博评论数据,了解一下?
  10. 去除List集合中的重复元素,并保持原有数据的初始顺序