首页 > 解决方案 > 在 Postgresql 中使用表重命名交换表内容时会出现什么问题?

问题描述

我需要自动更改 Postgresql 表中的大量行。我正在使用这样的技术:将数据添加到临时表,然后通过将 original 重命名为 not_matter_name 并将 temp 重命名为原始名称来交换表。此处描述了该技术。

但是这种方法被打破了。例如,我发现视图不会更新指向新表的指针,即使在名称交换后仍指向旧表。我找到的唯一解决方案是重新创建视图,这有点糟糕。

除了视图问题之外,这种技术还会出现什么问题?

我总体上做错了吗?有没有更好的快速交换表的解决方案,不会对其他 Postgresql 实体造成这样的副作用?


代码如下所示:

CREATE TABLE _temp_with_updated_data (like original_name including all);

--...MANY INSERTS TO _temp_with_updated_data

begin;
alter table original_name rename to ___doesnt_matter;
alter table _temp_with_updated_data rename to original_name;
alter table ___doesnt_matter to _temp_with_updated_data;
truncate table _temp_with_updated_data;
commit;

标签: postgresql

解决方案


另一个问题(除了视图)是外键,如果你有外键的话。当它被重命名时,它们也将遵循原始表。函数没有问题,因为它们在执行时解析表名,而不是在创建时解析。

如果您不喜欢重新创建视图,您可以使用从空基表继承的方法,并将视图指向该表。然后你不会继承旧的并继承新的。就我个人而言,我发现这种治疗方法比疾病更糟糕,只是重新创造了这些观点。您可以从 获取视图定义pg_dump -s,如果您还没有将它们隐藏在某个地方,但您需要自己整理出您需要哪些定义。

另一个问题可能只是性能问题,批量插入已索引的表可能会很慢。您可能希望使用 INCLUDING ALL EXCLUDING INDEXES 创建,然后在填充索引后构建索引。唉,PostgreSQL 并没有让第二部分变得容易。没有什么能像假设的 ALTER TABLE foo2 INCLUDE INDEXES LIKE foo1 这样您可以在事后运行(但同样pg_dump -s可以在这里提供帮助,以获取创建索引语句的列表)。但是,如果当前的性能不打扰您,那么首先不要排除索引,您以后就不需要构建它们。


推荐阅读