PostgreSQL 18 中文参考文档(未翻译部分保留英文)🌐 切换到英文原版 →

7.8. WITH 查询(公用表表达式) #

7.8.1. WITH 中的 SELECT
7.8.2. 递归查询
7.8.3. 公用表表达式物化控制
7.8.4. WITH 中的数据修改语句

WITH 查询(常被称为公用表表达式,Common Table Expressions,简称 CTE)提供了一种编写仅在单次查询生命周期内有效的辅助子查询语句的强大机制。它能够将极其庞大臃肿的复杂 SQL 拆解为多个逻辑清晰、高度模块化且可复用的具名中间结果单元:

WITH regional_sales AS (
    SELECT region, SUM(amount) AS total_sales
    FROM orders
    GROUP BY region
), top_regions AS (
    SELECT region
    FROM regional_sales
    WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
)
SELECT region,
       product,
       SUM(quantity) AS units,
       SUM(amount) AS sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;

7.8.1. WITH 中的 SELECT #

在 WITH 子句中声明的辅助查询通常为常规 SELECT 语句,其计算结果在主查询中像常规表一样被多次引用。

7.8.2. 递归查询 #

在 WITH 之后附加关键字 RECURSIVE,允许公用表表达式在定义体内部引用自身,从而实现强大的树状拓扑遍历或层级递归计算。递归 CTE 的标准写法为:一个基础非递归项(锚点),由 UNION(或 UNION ALL)连接一个引用了该 CTE 自身名称的递归项。典型的范例是计算从 1 到 100 的累加序列,或者递归查询组织架构汇报关系树。

7.8.2.2. 环路检测 #

在使用递归查询遍历图结构时,为了防止因数据中存在闭合环路而陷入无限死循环,可以使用 CYCLE 子句进行环路自动检测与追踪标记。

7.8.3. 公用表表达式物化控制 #

规划器默认会根据查询结构自主决定是否将辅助查询就地内联展开。通过在子查询前显式声明 AS MATERIALIZED,可以强制系统将其物化计算并缓存;反之通过 AS NOT MATERIALIZED 则强制内联折叠。

7.8.4. WITH 中的数据修改语句 #

在 WITH 子句中还可以使用数据修改语句(INSERT、UPDATE 或 DELETE 并附带 RETURNING 子句),从而在一个单一原子 SQL 事务中执行复杂的链式写操作。