CTE是仅在当前SQL语句有效的逻辑别名,不落地数据;临时表是会话级物理表,数据真实存储且可多次复用、索引和修改。

CTE 和临时表都能帮你把复杂查询拆开,但它们根本不是一类东西——一个像便签纸,一个像小笔记本。
作用范围不同
CTE 只在当前一条 SQL 语句里有效。写完 WITH,后面紧跟的 SELECT/INSERT/UPDATE 才能用它,换一行再写个 SELECT 就找不到了。
临时表是会话级的,只要没删、会话没断,后续所有查询都能反复访问。比如先算出高价值用户存进 #high_value,之后 JOIN 用户表、关联订单表、导出报表,全都可以用。
数据是否真实落地
CTE 不存数据,只是“重写一遍查询逻辑”的语法糖。如果主查询里引用了两次 CTE,数据库大概率会执行两次底层 SELECT(除非优化器做了物化,但不能依赖)。
临时表会真正在 tempdb(或内存)里建一张表,数据写进去就固定了。后续读取不重复计算,还能加索引、做 UPDATE、分批 INSERT,行为和普通表几乎一致。
适用场景明显分开
- 用 CTE:想让一段嵌套逻辑更清楚、查组织架构树、写个带层级的菜单展开、或者只在一个查询里复用中间结果
- 用临时表:中间结果要被多个独立 SQL 复用、数据量大到需要索引加速、要边算边改(比如标记处理状态)、或者调试时想 inspect 中间数据
语法与维护成本
CTE 写法轻量,WITH 开头,无须 CREATE,也不用 DROP,用完即弃,零管理负担。
临时表要显式创建(CREATE TEMP TABLE 或 SELECT INTO),建议手动加索引,也最好显式 DROP(尤其在长会话或存储过程中),否则可能堆积或影响性能。










