PostgreSQL中ON COMMIT PRESERVE ROWS是冗余的,默认即此行为;它仅在显式声明ON COMMIT DELETE ROWS后才可覆盖,且不可ALTER修改;MySQL不支持该子句,Oracle则要求GLOBAL TEMPORARY TABLE。 PostgreSQL 里 O
ON COMMIT PRESERVE ROWS 不起作用?检查事务模式很多开发者第一次在PostgreSQL里用ON COMMIT PRESERVE ROWS时,可能会感到困惑:明明加了这句,怎么感觉跟没加一样?其实,问题的关键就在于理解PostgreSQL临时表的默认行为。
简单来说,PostgreSQL的临时表天生就是“会话级”的。这意味着,ON COMMIT PRESERVE ROWS这个子句在PostgreSQL里其实是冗余的——它描述的就是系统默认的行为。这个子句真正起作用的地方,是在你创建临时表时已经声明了ON COMMIT DELETE ROWS之后,想用一个新的CREATE语句去覆盖它。但这里有个常见的“坑”:已经存在的临时表,其提交行为是无法通过ALTER TABLE来修改的。
长期稳定更新的攒劲资源: >>>点此立即查看<<<
所以,当你发现提交事务后数据还在(或者你期望它被清空时反而没清空),根源往往不是语法错误,而是没搞清楚临时表与事务的关系。需要明确一点:临时表本身不参与常规的事务回滚,它的“提交行为”特指在COMMIT这个动作发生时,是否自动清空表中的数据行,而且这个特性只对声明了ON COMMIT DELETE ROWS的临时表有效。

CREATE TEMP TABLE t(x int) ON COMMIT PRESERVE ROWS 等价于不写该子句(PostgreSQL 默认行为)ON COMMIT DELETE ROWS,后续想改语义——但注意:不能 ALTER 修改已存在的临时表的 commit actionSECURITY DEFINER,还要确认当前用户有 TEMP 权限,否则建表失败但错误可能被静默吞掉ON COMMIT PRESERVE ROWS,替代方案要绕开事务绑定如果你从PostgreSQL转向MySQL,想把ON COMMIT PRESERVE ROWS这套逻辑搬过去,那肯定会碰壁。MySQL的CREATE TEMPORARY TABLE从设计上就是会话级且非事务性的,数据在会话结束前会一直保留,提交事务对它没有影响。因此,MySQL根本不支持ON COMMIT这个子句。如果你强行写上,等待你的就是一句经典的ERROR 1064 (42000): You ha ve an error in your SQL syntax。
那在MySQL里怎么实现类似的需求呢?通常得换个思路,绕开数据库原生的“事务提交时保留”语义:
_tmp_ 或 _tmp_,应用层负责建和删ENGINE=MEMORY)+ 显式 DROP TEMPORARY TABLE 控制生命周期,但注意 MEMORY 表不支持 BLOB/TEXT,且数据全在内存,OOM 风险高ON COMMIT PRESERVE ROWS 要配 GLOBAL TEMPORARY TABLE在几个主流数据库中,Oracle是少数真正需要并完整实现ON COMMIT PRESERVE ROWS语法的。但它有个严格的前置条件:这个子句必须和GLOBAL TEMPORARY TABLE(全局临时表)一起使用。漏掉GLOBAL关键字,或者误用旧的TEMPORARY语法,都会导致错误。
CREATE GLOBAL TEMPORARY TABLE t(x INT) ON COMMIT PRESERVE ROWSCREATE TEMPORARY TABLE t(x INT) ON COMMIT PRESERVE ROWS(报错 ORA-00902)PRESERVE ROWS 下,COMMIT 不清空,ROLLBACK 也不清空,只有会话退出或显式 TRUNCATE 才清PRESERVE ROWS 表的数据会一直留在 PGA,长连接容易累积,建议业务逻辑结束时主动 TRUNCATE看到这里,你可能已经发现了,不同数据库对“临时表生命周期”的管理哲学差异巨大。PostgreSQL默认就是会话保留;MySQL干脆不支持事务绑定;Oracle则提供了DELETE和PRESERVE两种精细的事务模型。这种底层差异意味着,不存在一套放之四海而皆准的兼容写法。
任何试图在ORM或中间件层用统一SQL模板来适配这三种数据库的做法,最终都会在某个环节出问题。
ON COMMIT PRESERVE ROWS 到 MySQL 或 SQL Server(它也不支持),必然报错#t)连 DDL 都不能跨批执行,CREATE #t 和后续 INSERT 必须在同一 batchdatabaseProductName 分支处理,建表、填充、清理全部由具体方言实现说到底,会话级临时表的“临时性”,并不是靠一句语法糖来保证的,而是由数据库内核对于对象生命周期的根本定义所决定的。直接拷贝一行SQL解决不了问题,关键在于先看清楚,你正在使用的数据库,遵循的是哪一套游戏规则。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述