mysql预编译表名_slq预编译与mybatis
# 一、SQL 语句的执行处理
## 1.1 即时 SQL
一条 SQL 在 DB 接收到最终执行完毕返回,大致的过程如下:
1. 词法和语义解析;
2. 优化 SQL 语句,制定执行计划;
3. 执行并返回结果;
如上,一条 SQL 直接是走流程处理,一次编译,单次运行,此类普通语句被称作 Immediate Statements (即时 SQL,每次执行都会经过语法检查语义解析,优化等过程)。
## 1.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 版本都是支持这一语法的。
语法:
## 2.1 定义预处理语句
```
PREPARE stmt_name FROM preparable_stmt(sql语句);
```
## 2.2 执行预处理语句
```
EXECUTE stmt_name [USING @var_name [, @var_name] ...];
```
## 2.3 删除(释放)定义
```
{DEALLOCATE | DROP} PREPARE stmt_name;
```
## 2.4 例子
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)
~~~
## 2.4 解决无法传参问题
我们知道,对于 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级
![](https://img2018.cnblogs.com/blog/1113510/201811/1113510-20181101192302151-157684852.png)
可以通过 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)
~~~
mysql预编译表名_slq预编译与mybatis相关推荐
- mysql预编译表名_JDBC预编译语句表名占位异常
有时候,我们有这样的需求,需要清空多个表的内容,这样我们有两种做法,可用delete from table 或 truncate table table,两种方法视情况而定,前者只是一条条的删除表数据 ...
- MySQL获取Schema表名和字段信息
MySQL获取Schema表名和字段信息 获取表名 select TABLE_NAME,TABLE_TYPE,ENGINE,TABLE_ROWS,TABLE_COMMENT,CREATE_TIME,U ...
- MySQL 重命名表名 2种方法
今天用 phpMyAdmin 创建了一张表后,发现"表名字"取得有点后悔,想直接删除重新创建一个,但是这个表的字段又有点多,居然有30多个字段,后来就找到了MySQL表重命名的方法 ...
- MySQL 8 忽略表名大小写
MySQL 8 忽略表名大小写 文章目录 MySQL 8 忽略表名大小写 一.修改步骤: 1.备份数据 2.停止MySQL服务 3.删除数据目录 4.修改 `my.cnf` 配置文件 5.重新初始 ...
- mysql批量修改表名前缀
mysql中修改表名前缀的语句为:alert table 旧表名 rename to 新表名: mysql没有直接批量修改表名的方法,但是我们可以通过批量生成修改语句来达到批量修改表名的效果. 代码: ...
- linux mysql 修改表名_Linux下mysql怎么设置表名?
Linux下mysql可以通过"ALTER TABLE 旧表名 RENAME [TO] 新表名;"语句来修改表名:还可以通过配置my.cnf文件,修改"lower_cas ...
- MySQL 批量修改表名
MySQL 批量修改表名 1.执行查询SQL 2.执行修改SQL 功能: 将数据库 jeecg-boot 中的表名前缀是 ACT_ 开头的表名替换为 CAMUNDA_ACT_ 1.执行查询SQL -- ...
- mysql批量修改表名、删除表
mysql批量修改表名 第一步:得到所有需要修改的表名和对于得修改表名语句 SELECT CONCAT( 'ALTER TABLE ', table_name, ' RENAME TO ', REPL ...
- MySQL修改数据表名
修改数据表,包括:修改表名.修改字段名.修改字段的数据类型等. MySQL中,修改数据表的操作都是使用ALTER TABLE 修改表名 ALTER TABLE 旧表名 RENAME [TO] 新表名: ...
最新文章
- 计算机的潜意识--从机器学习谈起
- Vue为v-html中标签添加CSS样式
- 划分字母区间(双指针,贪心)
- 带有示例的Python File readlines()方法
- 【转】LAMP网站架构方案分析【精辟】
- php mb开启,windows环境下如何为php开启mb_string函数库功能
- 整理一些质量不错的教程、博客、论坛
- 重装系统大师计算机硬件不兼容,360重装系统教你如何处理提示不兼容的软件
- Unexpected token
- 彩信发送和接收关键流程
- 电脑录音软件哪个比较专业
- day13课后总结App
- PMOS和NMOS引脚及封装
- OpenCV4学习记录(一)解决第一步OpenCV4.5.1+VS2019+CMake
- UE4-制作真实场景三维地形
- 计算机能显示u盘吗,U盘插到电脑上,能检测到这设备,但是在“我的电脑”里没有显示U盘...
- mysql 授权 all_mysql使用grant ALL privileges命令给用户授权
- [项目] 网易云音乐项目总结
- 在Windows桌面壁纸上加字方法
- R数据分析实战——奥运会120年历史