WITH 子句允许在 SELECT、INSERT 或 UPDATE 语句之前定义一个或多个临时结果集,这些结果集被称为公用表表达式 (CTE)。它类似于定义了仅在当前查询范围内有效的“局部视图”。核心价值
消除冗余(方便维护):将多次引用的复杂子查询提取到顶部,减少代码重复,降低维护成本。
提升可读性:将嵌套过深、逻辑复杂的 SQL “扁平化”,使其更接近人类阅读习惯(从上到下执行逻辑)。
冲突隔离:定义的别名仅在当前查询结束后即销毁,不会与数据库中的实际表名或视图名产生冲突。
跨系统兼容:广泛支持 ANSI SQL 标准(如 Oracle、PostgreSQL、MySQL 8.0+ 等),增强了代码的可移植性。
使用限制
递归支持:当前版本不支持递归查询(即
WITH RECURSIVE),而某些其他数据库系统支持该功能。代码示例
多重定义与引用
-- 定义两个临时表 t1 和 t2,并执行合并插入WITHt1 AS (SELECT 1 AS val),t2 AS (SELECT 2 AS val)INSERT INTO tabSELECT * FROM t1UNION ALLSELECT * FROM t2;
嵌套作用域定义
CTE 也支持在不同查询层级进行定义。以下示例展示了外层定义与内层嵌套定义的结合使用:
-- 在外层定义 t1,同时在 UNION ALL 的分支内局部定义 t2WITH t1 AS (SELECT 1)(WITH t2 AS (SELECT 2)SELECT * FROM t2)UNION ALLSELECT * FROM t1;
与传统子查询对比
特性 | 传统子查询 (Subquery) | WITH 子句 (CTE) |
逻辑顺序 | 由内而外(嵌套式) | 由上而下(流式) |
复用性 | 无法直接复用,需多次书写逻辑 | 一次定义,多次引用 |
代码维护 | 随着嵌套加深,代码极难维护 | 逻辑清晰,易于调试 |