赞
踩
CTE(Common Table Expressions),是一个可以在单个语句范围内被创建的临时结果集,可在该语句中被多次引用。
CTE通常以 WITH
关键字开头,后跟一个或多个子句,以逗号分隔。每个子句都提供一个结果集。
具体请看以下示例:
WITH
cte1 AS (SELECT a, b FROM table1),
cte2 AS (SELECT c, d FROM table2)
SELECT b, d FROM cte1 JOIN cte2
WHERE cte1.a = cte2.c;
在这个语句中,两个结果集分别被命名为cte1
,cte2
,并在后续的SELECT
查询中使用了它们。
结果集不仅能在SELECT
查询中被引用,也可以被其他CTE语句引用,从而可以使CTE能够基于其他CTE进行定义。
CTE也可以引用自身来定义递归 CTE。递归 CTE 的常见应用包括分层或树结构数据的系列生成和遍历。
CTE 是 DML 语句语法的可选部分。它们是使用 WITH
子句定义:
with_clause:
WITH [RECURSIVE]
cte_name [(col_name [, col_name] ...)] AS (subquery)
[, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
cte_name
表示单个通用表表达式的名字,可以被当作一个临时表被引用。(subquery)
部分是生成CTE结果集的子查询部分,括号是必需的。RECURSIVE
关键字。CTE结果集临时表的列名,即 [(col_name [, col_name] ...)]
部分,遵从以下原则:
cte_name
后面是带括号的名称列表,即明确指定了列名,如下:WITH cte (col1, col2) AS
(
SELECT 1, 2
UNION ALL
SELECT 3, 4
)
SELECT col1, col2 FROM cte;
那么,子查询的结果集返回列数比如和括号中的列个数相同。
WITH cte AS
(
SELECT 1 AS col1, 2 AS col2
UNION ALL
SELECT 3, 4
)
SELECT col1, col2 FROM cte;
WITH
适用于哪些上下文场景?SELECT
, UPDATE
, 以及 DELETE
等语句的开头使用:WITH ... SELECT ...
WITH ... UPDATE ...
WITH ... DELETE ...
SELECT ... WHERE id IN (WITH ... SELECT ...) ...
SELECT * FROM (WITH ... SELECT ...) AS dt ...
SELECT
语句的语句中,紧接在 SELECT
之前使用:INSERT ... WITH ... SELECT ...
REPLACE ... WITH ... SELECT ...
CREATE TABLE ... WITH ... SELECT ...
CREATE VIEW ... WITH ... SELECT ...
DECLARE CURSOR ... WITH ... SELECT ...
EXPLAIN ... WITH ... SELECT ...
同一级别只允许一个 WITH
子句。不能在同一级别后跟另一个 WITH
,因此以下语句是不合法的:
WITH cte1 AS (...) WITH cte2 AS (...) SELECT ...
要使语句合法,使用一个 WITH
子句,并用逗号分隔子句:
WITH cte1 AS (...), cte2 AS (...) SELECT ...
然而,如果它们出现在不同级别,则一个语句可以包含多个 WITH
子句:
WITH cte1 AS (SELECT 1)
SELECT * FROM (WITH cte2 AS (SELECT 2) SELECT * FROM cte2 JOIN cte1) AS dt;
一个 WITH
子句可以定义一个或多个通用表表达式,但每个CTE名称必须对该子句是唯一的。以下是不合法的:
WITH cte1 AS (...), cte1 AS (...) SELECT ...
为了使语句合法,用唯一名称定义CTEs:
WITH cte1 AS (...), cte2 AS (...) SELECT ...
一个CTE可以在其自身或者其他CTE中被引用。
引用自身的CTE是递归CTE。
一个CTE中被引用的其他CTE需要在其前被定义。
该约束排除了相互递归的CTE,cte1引用cte2,cte2引用cte1。其中一个引用必须是稍后定义的CTE,这是不允许的。
在给定查询块中的CTE可以引用在更外层级别的查询块中定义的CTE,但不能引用在更内层级别的查询块中定义的CTE。
对于具有相同名称的对象的引用解析,派生表隐藏CTE;而CTE隐藏基本表、临时表和视图。名称解析是通过在同一查询块中搜索对象,然后逐个到更外层块中进行,直到找到该名称的对象为止。
请参考文章:MySQL CTEs通用表表达式:进阶学习-递归通用表表达式
https://blog.csdn.net/kaka_buka/article/details/136512460
官方文档
https://dev.mysql.com/doc/refman/8.0/en/with.html
博客文章
https://blog.csdn.net/w13966597931/article/details/133221384
https://blog.csdn.net/a2272062968/article/details/131888595
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。