WITH
Common Table Expression (CTE) 是一个临时结果集,可以在 SQL 语句中多次引用,以提高语句的可读性和执行效率。你可以应用 WITH
语句来使用 Common Table Expressions。
概述
WithClause:
- WithClause
WithClause ::=
"WITH" WithList
| "WITH" "RECURSIVE" WithList
WithList:
- WithList
WithList ::=
WithList ',' CommonTableExpr
| CommonTableExpr
CommonTableExpr:
- CommonTableExpr
CommonTableExpr ::=
Identifier IdentListWithParenOpt "AS" SubSelect
IdentListWithParenOpt:
- IdentListWithParenOpt
IdentListWithParenOpt ::=
( '(' IdentList ')' )?
示例
非递归 CTE:
WITH cte AS (SELECT 1, 2) SELECT * FROM cte t1, cte t2;
+---+---+---+---+
| 1 | 2 | 1 | 2 |
+---+---+---+---+
| 1 | 2 | 1 | 2 |
+---+---+---+---+
1 row in set (0.00 sec)
递归 CTE:
WITH RECURSIVE cte(a) AS (SELECT 1 UNION SELECT a+1 FROM cte WHERE a < 5) SELECT * FROM cte;
+---+
| a |
+---+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+---+
5 rows in set (0.00 sec)
MySQL 兼容性
- 在严格模式下,当递归计算的数据长度超过种子部分的数据长度时,TiDB 会返回警告,而 MySQL 会返回错误。在非严格模式下,TiDB 的行为与 MySQL 一致。
- 递归 CTE 的数据类型由种子部分决定。在某些情况下(如函数),种子部分的数据类型与 MySQL 不完全一致。
- 在多个
UNION
/UNION ALL
操作符的情况下,MySQL 不允许UNION
后面跟UNION ALL
,而 TiDB 支持。 - 如果 CTE 的定义存在问题,TiDB 会报错,而如果 CTE 未被引用,MySQL 不会报错。