绝大多数场景必须用 #temp 而非 @table,因 @table 无统计信息、优化器恒按5行估算,致执行计划劣化;#temp 支持索引、统计信息更新及事务回滚,>100 行或需多次 join/group by 时性能显著更优。

SQL Server 里该用 #temp 还是 @table?
绝大多数场景必须用 #temp,不是 @table。优化器对 @table 固定按 5 行估算,插了 5000 行也照旧——JOIN 可能选嵌套循环而非哈希连接,WHERE 条件走全表扫描,甚至内存溢出到 tempdb。
- 数据量 > 1000 行,或需多次
JOIN/ORDER BY/GROUP BY,必须用#temp - ≤ 100 行且只在单个语句里用(比如简单过滤后直接返回),可选
@table - 函数中只能用
@table,但它不支持UPDATE STATISTICS,也不能建非主键索引 -
#temp支持CREATE CLUSTERED INDEX,@table不支持ALTER TABLE或显式索引
为什么不能随便用 ##temp?
##temp 是全局的,所有会话都能看到。高并发下 A 用户刚写进 ##tmp_result 的中间值,B 用户下一秒就可能读到,甚至覆盖——报表调度、API 批量调用时极易脏读或主键冲突。
-
#temp是会话级隔离,SQL Server 断开连接时自动删,但异常退出时未必立刻释放 - 务必在开头加
DROP TABLE IF EXISTS #tmp_result,否则重试执行直接报错There is already an object named '#tmp_result' in the database - 别依赖“自动清理”,尤其调试阶段反复执行,
DROP是安全底线
MySQL 和 PostgreSQL 怎么写才不翻车?
它们根本不认 # 语法,硬写会建出永久表或报错。
- MySQL 必须写
CREATE TEMPORARY TABLE tmp_calc,漏掉TEMPORARY关键字就真建到磁盘上,第二次执行报Table 'tmp_calc' already exists - MySQL 不支持
SELECT INTO,只能先CREATE TABLE再INSERT SELECT;含TEXT/BLOB字段会强制退化为磁盘表,拖慢性能 - PostgreSQL 必须加
ON COMMIT DROP,只写CREATE TEMP TABLE t1会让表活到会话结束——Web 长连接复用会话时,第二次调用直接卡在relation "t1" already exists - PostgreSQL 上
TRUNCATE对临时表无效,ON COMMIT DROP已接管生命周期
字段名带空格或 NULL 怎么处理?
字段名含空格、连字符或保留字时,SELECT INTO #tmp FROM () t 会解析失败;NULL 值参与 JOIN 或 WHERE 容易导致结果意外为空。
- 显式用方括号包裹:
SELECT [user name] AS [user name] INTO #tmp FROM ... - 避免用
SELECT INTO自动推导结构,改用CREATE TABLE #tmp (...)显式定义 - 中间结果存进临时表后,后续
WHERE或JOIN条件一旦涉及NULL,记得用IS NULL或COALESCE显式处理
ON COMMIT DROP 是必需项,不是可选项;MySQL 漏掉 TEMPORARY 就等于把临时数据落盘——这些坑不会报错,只会静默污染生产环境。










