网站首页 > 博客文章 正文
前言
Mysql 8 正式发布了,新增了很多优秀特性,之后我会挑些重点来分享。
下面和大家一起熟悉下CTE(Common Table Expressions)通用表表达式。
CTE 是什么
派生表大家都比较熟悉了,CTE 就是针对派生表来的,可以说是增强的派生表,或者说时派生表的替换。
派生表是FROM
中的子查询,例如:
SELECT ... FROM (subquery) AS derived, t1 ...
CTE 就像派生表,但它的声明是在查询块儿之前,而不是在FROM
中,例如:
WITH derived AS (subquery) SELECT ... FROM derived, t1 ...
CTE 的语法
看几个简单的示例:
CTE 的好处
CTE 相较于派生表有4个明显的优势:
(1)更好的可读性
派生表的形式:
SELECT ... FROM t1 LEFT JOIN ((SELECT ... FROM ...) AS dt JOIN t2 ON ...) ON ...
CTE的形式:
WITH dt AS (SELECT ... FROM ...) SELECT ... FROM t1 LEFT JOIN (dt JOIN t2 ON ...) ON ...
(2)可以被多次引用
派生表不能被引用两次,例如:
SELECT ... FROM (SELECT a, b, SUM(c) s FROM t1 GROUP BY a, b) AS d1 JOIN (SELECT a, b, SUM(c) s FROM t1 GROUP BY a, b) AS d2 ON d1.b = d2.a;
而 CTE 可以,例如:
WITH d AS (SELECT a, b, SUM(c) s FROM t1 GROUP BY a, b) SELECT ... FROM d AS d1 JOIN d AS d2 ON d1.b = d2.a;
(3)可以引用其他的 CTE
派生表不能引用其他派生表,例如:
SELECT ... FROM (SELECT ... FROM ...) AS d1, (SELECT ... FROM d1 ...) AS d2 ... ERROR: 1146 (42S02): Table ‘db.d1’ doesn’t exist
CTE 可以引用其他的 CTE,例如:
WITH d1 AS (SELECT ... FROM ...), d2 AS (SELECT ... FROM d1 ...) SELECT FROM d1, d2 ...
(4)性能的提升
派生表是具体化的,每个派生表都是一个具体化的存在,就会产生性能问题,例如更多的空间、耗费更多的时间……
CTE 只会被创建一次,不管被引用了多少次
示例
(1)生成 1-10 的数字
先从一个简单的例子开始,生成 1-10 的数字
WITH RECURSIVE my_cte AS ( SELECT 1 AS n UNION ALL SELECT 1+n FROM my_cte WHERE n<10 ) SELECT * FROM my_cte; +------+ | n | +------+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | | 10 | +------+
简单分析下这个例子:
这个CTE名字是my_cte,需要注意的是名字前面多了一个关键字RECURSIVE,说明这个CTE是递归形式的
括号中间是CTE的定义
SELECT那句是对my_cte的使用
SELECT 1 AS n
是初始设置,这一行是用来定义my_cte的列,只有一列,类型为INT,名字为nSELECT 1+n FROM my_cte WHERE n<10
这句的意思是:从 my_cte 中拿 <10 的行,然后产生一行新记录,对n进行增加
所以 mysql 会做以下步骤:
迭代0:创建初始行,S0:S0={1}
迭代1:基于 S0 进行处理,产生新数据 S1={1+1}={2}
迭代2:基于 S1,产生 S2={1+2}={3}
...
迭代9:基于 S8,产生 S9={1+9}={10}
迭代10:基于 S9,发现没有匹配n<10的,所以没有产出,并使循环终止
my_cte 的最终结果就是对S0,S1,...,S9进行union
(2)使用 CTE 创建一个表
USE test; CREATE TABLE numbers WITH RECURSIVE my_cte(n) AS ( SELECT 1 UNION ALL SELECT 1+n FROM my_cte WHERE n<6 ) SELECT * FROM my_cte; Query OK, 6 rows affected (0,40 sec) SELECT * FROM numbers; +------+ | n | +------+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +------+
(3)用于 INSERT
INSERT INTO numbers WITH RECURSIVE my_cte(n) AS ( SELECT 1 UNION ALL SELECT 1+n FROM my_cte WHERE n<6 ) SELECT * FROM my_cte; Query OK, 6 rows affected (0,12 sec) SELECT * FROM numbers; +------+ | n | +------+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +------+
(4)在 UPDATE 中使用:
WITH RECURSIVE my_cte(n) AS ( SELECT 1 UNION ALL SELECT 1+n FROM my_cte WHERE n<6 ) UPDATE numbers, my_cte SET numbers.n=0 WHERE numbers.n=my_cte.n*my_cte.n; Query OK, 4 rows affected (0,01 sec) SELECT * FROM numbers; +------+ | n | +------+ | 0 | | 2 | | 3 | | 0 | | 5 | | 6 | | 0 | | 2 | | 3 | | 0 | | 5 | | 6 | +------+
(5)在 DELETE 中使用:
DELETE FROM numbers WHERE numbers.n > ( WITH RECURSIVE my_cte(n) AS ( SELECT 1 UNION ALL SELECT 1+n FROM my_cte WHERE n<6 ) # Half the average is 3.5/2=1.75 SELECT AVG(n)/2 FROM my_cte ); Query OK, 4 rows affected (0,07 sec) SELECT * FROM numbers; +------+ | n | +------+ | 0 | | 0 | | 0 | | 0 | +------+
Mysql 8 实践环境搭建
我是使用 docker 安装的Mysql 8.0.11,我感觉这是最简单的方式。
启动正常,但连接mysql时报错:
MySQL said: Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(/usr/local/lib/plugin/caching_sha2_password.so, 2): image not found
意思是caching_sha2_password这个认证插件不能被加载。
网上查了一下,原因是mysql8改变了认证模式,解决方式是在启动容器时指定参数:
docker run -p 3306:3306 --name mysql8 -e MYSQL_ROOT_PASSWORD=111111 -d mysql:8.0.11 --default-authentication-plugin=mysql_native_password
重点是添加了:
--default-authentication-plugin=mysql_native_password
之后就可以正常登陆了,使用docker mysql作为客户端登录的命令:
docker run -it --link mysql8:mysql --rm mysql sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"'
这是我遇到的一个问题,如果你也是使用docker来实践mysql8,这个经验会帮您节省一些时间。
猜你喜欢
- 2024-09-10 解决Navicat连接 Mysql 8 出现1251- Client does not support错误
- 2024-09-10 win10安装mysql遇到的坑(win10安装mysql5.5)
- 2024-09-10 MySQL系列-二进制包安装(v8.0.24)
- 2024-09-10 Win10+docker+Laradock(下篇):Docker的基本操作与项目开发配置
- 2024-09-10 为Debezium配置MySQL单机版(mysqld 指定配置文件)
- 2024-09-10 Java 连接 MySQL 8.0 排错案例-爱可生
- 2024-09-10 MySQL数据库下载、安装、配置、卸载
- 2024-09-10 不要再原地踏步了,升级到 MySQL 8.x 的 6 大理由!
- 2024-09-10 Django + MySQL 8 开发环境用 Docker来部署
- 2024-09-10 【每日一学】数据库大揭秘:MySQL 事务学习手册,精通数据操作!
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)