前言

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 的语法

看几个简单的示例:

WITH qn AS (SELECT a FROM t1)

SELECT * from qn;

WITH qn AS (SELECT a+2 AS a, b FROM t1)

UPDATE t1, qn SET t1.a=qn.a + 10 WHERE t1.a - qn.a = 0;

WITH qn(a, b) AS (SELECT a+2, b FROM t2)

DELETE t1 FROM t1, qn WHERE t1.a - qn.a = 0;

INSERT INTO t2

WITH qn AS (SELECT 10*a AS a FROM t1)

SELECT * from qn;

SELECT * FROM t1 WHERE t1.a IN

(WITH cte as (SELECT * FROM t1 AS t2 LIMIT 1)

SELECT a + 0 FROM 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,名字为n

SELECT 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,这个经验会帮您节省一些时间。

点击下面的“阅读原文”查看文章列表

mysql cte的好处_Mysql 8 重要新特性 - CTE 通用表表达式相关推荐

  1. mysql计算三角形斜边_MySQL 5.7新特性之Generated Column(函数索引)

    MySQL 5.7引入了Generated Column,这篇文章简单地介绍了Generated Column的使用方法和注意事项,为读者了解MySQL 5.7提供一个快速的.完整的教程.这篇文章围绕 ...

  2. mysql is双竖线_MySQL 5.0 新特性教程 存储过程:第二讲

    MySQL 5.0 新特性教程 存储过程:第二讲推荐查看本文HTML版本 什么样的SQL语句在Mysql存储过程中才是合法的呢?你可以创建一个包含INSERT, UPDATE,DELETE, SELE ...

  3. mysql cte_MySQL 8 中CTE 通用表表达式,CTE 是什么,CTE 的好处

    前言 Mysql 8 正式发布了,新增了很多优秀特性,之后我会挑些重点来分享. 下面和大家一起熟悉下 CTE(Common Table Expressions)通用表表达式. CTE 是什么 派生表大 ...

  4. MySQL 8.0新特性--CTE Recurive(二)

    上一篇介绍了CTE的基本用法,参考MySQL 8.0新特性--CTE(一),本篇再来介绍一下CTE Recurive递归. 1.什么是CTE Recurive? A recursive common ...

  5. MySQL基础篇13【MySQL8.0新特性】

    目录 1. MySQL8新特性概述 1.1 MySQL8.0 新增特性 1.2 MySQL8.0移除的旧特性 新特性1:窗口函数 2.1 使用窗口函数前后对比 2.2 窗口函数分类 2.3 语法结构 ...

  6. Mysql Connector 5.1 好用的新特性

    Mysql Connector 5.1 好用的新特性 转载自并发编程网 – ifeve.com本文链接地址: Mysql Connector 5.1 好用的新特性 Mysql Connector 5. ...

  7. 《MySQL 入门教程》第 20 篇 通用表表达式

    文章目录 20.1 简单 CTE 20.2 递归 CTE 20.3 递归限制 上一篇介绍了子查询的各种概念和作用,本篇我们讨论一个和派生表类似但更加强大的功能:通用表表达式. 通用表表达式(Commo ...

  8. Oracle 11g新特性之--只读表(read only table)

    Oracle 11g新特性之--只读表(read only table)       Oracle11g推出了一个新的特性,可以将table置于read only状态,处于该状态的table的不能执行 ...

  9. Oracle11g新特性导致空表不能导出问题

        ORACLE 11G在用EXP导出时,发现空表(没有数据或者没有用过的表)不能导出了. 查了一下资料,说是Oracle 11G中有个新特性,当表无数据时,不分配segment,以节省空间,所以 ...

最新文章

  1. STM32-USART发送程序
  2. LA4234 Binary Clock(进制转换)
  3. 全球及中国软磁镍合金行业供需前景与投资策略研究报告2022版
  4. 【机器视觉】 translate_measure算子
  5. leetcode336. 回文对(字典树)
  6. c51为啥要宏定义时钟_51单片机时钟实训报告
  7. 干货收藏!639页《深度学习:Deep Learning》图文并茂课程PPT
  8. 让数据库支持SQL 2005 CLR 的必要条件
  9. java模拟记事本的一些功能
  10. 定位叠放次序z-index(HTML、CSS)
  11. ERP的模块流程/组织架构和其他基础知识
  12. 整型数字的英文表达和中文表达
  13. 电脑系统故障维修,系统C盘满了怎么办?教你c盘清理方法
  14. 【路径规划】基于粒子群算法求解带时间窗的车辆路径规划问题VRPTW模型matlab源码
  15. Android开发中WIFI和GPRS网络的切换
  16. Python3初步实践教程概要
  17. 北大出疯子,清华出傻子,人大出混混
  18. 使用ChatGPT和EZDML迅速高效生成可运行的软件系统原型
  19. HDU 3234 Exclusive-OR(并查集)
  20. cs109-energy+哈佛大学能源探索项目 Part-3(探索性分析)

热门文章

  1. 中国冷兵器时代的十大勇将
  2. js es6数组拼接
  3. warning MSB8028: The intermediate directory (Debug) contains files shared from an
  4. 仿微信在对话框文字中插入Emoji表情包
  5. 易阳指 java_我有个小外甥,姓易,请帮忙起个好名字?
  6. 阿里云ecs 发邮件
  7. CKEditor配置数学公式编辑器
  8. GT测试使用方法---APP工具
  9. python办公图表怎么画,用python绘制常用图表(一),上
  10. debain修改服务器网卡名,Debian 系统修改网卡ens33名称为 eth0