PostgreSQL中ON COMMIT PRESERVE ROWS是冗余的,默认即此行为;它仅在显式声明ON COMMIT DELETE ROWS后才可覆盖,且不可ALTER修改;MySQL不支持该子句,Oracle则要求GLOBAL TEMPORARY TABLE。
PostgreSQL 里 ON COMMIT PRESERVE ROWS 不起作用?检查事务模式
postgresql 的临时表默认就是会话级的,on commit preserve rows 实际上是冗余的——它只在 create temporary table 声明为 on commit delete rows 后才可被显式覆盖。但很多人误以为加了它就能“延长生命周期”,结果发现提交后数据还在,或反而丢了,根源常是没意识到:临时表本身不参与事务回滚,其“提交行为”仅影响 commit 时是否清空行,且仅对 on commit delete rows 表生效。
-
CREATE TEMP TABLE t(x int) ON COMMIT PRESERVE ROWS等价于不写该子句(PostgreSQL 默认行为) - 真正需要它的地方,是你先设了
ON COMMIT DELETE ROWS,后续想改语义——但注意:不能 ALTER 修改已存在的临时表的 commit action - 如果在函数内或匿名块中建临时表,且该函数用
SECURITY DEFINER,还要确认当前用户有TEMP权限,否则建表失败但错误可能被静默吞掉
MySQL 没有 ON COMMIT PRESERVE ROWS,替代方案要绕开事务绑定
MySQL 的 CREATE TEMPORARY TABLE 本质是会话级、非事务性对象,天生就“提交也不删”,所以它压根不支持 ON COMMIT 子句。强行照搬 PostgreSQL 写法会直接报错:ERROR 1064 (42000): You have an error in your SQL syntax。这时候得换思路:
- 用普通表 + 命名规则 + 定期清理:比如表名带
_tmp_<pid>或_tmp_<connection_id()>,应用层负责建和删 - 用内存表(
ENGINE=MEMORY)+ 显式DROP TEMPORARY TABLE控制生命周期,但注意MEMORY表不支持 BLOB/TEXT,且数据全在内存,OOM 风险高 - 若必须和事务强绑定(如中间计算结果),只能用普通表配合唯一 session ID 字段 + 应用层手动清理,别指望数据库自动收尾
Oracle 的 ON COMMIT PRESERVE ROWS 要配 GLOBAL TEMPORARY TABLE
Oracle 是少数真正实现该语法的数据库,但它要求前置条件严格:必须是 GLOBAL TEMPORARY TABLE,且建表时明确指定 ON COMMIT PRESERVE ROWS。漏掉 GLOBAL 关键字,或者写成 TEMPORARY(旧语法),都会导致语法错误或语义不符。
- 正确写法:
CREATE GLOBAL TEMPORARY TABLE t(x INT) ON COMMIT PRESERVE ROWS - 错误写法:
CREATE TEMPORARY TABLE t(x INT) ON COMMIT PRESERVE ROWS(报错 ORA-00902) - 注意:这种表的 DDL 会被所有会话共享,但数据完全隔离;
PRESERVE ROWS下,COMMIT不清空,ROLLBACK也不清空,只有会话退出或显式TRUNCATE才清 - 性能上,
PRESERVE ROWS表的数据会一直留在 PGA,长连接容易累积,建议业务逻辑结束时主动TRUNCATE
跨数据库兼容写法不存在,别试图抽象一层
不同数据库对“临时表生命周期”的控制粒度差异太大:PostgreSQL 默认会话级、MySQL 强制会话级、Oracle 分 DELETE/PRESERVE 两种事务模型。任何试图用统一 SQL 模板适配三者的做法,最终都会在某个环境里栽跟头。
- ORM 层硬塞
ON COMMIT PRESERVE ROWS到 MySQL 或 SQL Server(它也不支持),必然报错 - 用配置开关切换建表语句?可行,但要注意:SQL Server 的临时表(
#t)连 DDL 都不能跨批执行,CREATE #t和后续INSERT必须在同一 batch - 最稳妥的做法:把临时表逻辑下沉到 DAO 层,按
databaseProductName分支处理,建表、填充、清理全部由具体方言实现
会话级临时表的“临时性”不是靠语法糖保证的,而是靠数据库内核对对象生命周期的定义方式。抄一行 SQL 解决不了问题,得先看清自己用的是哪套规则。

















