是否可以从PostgreSQL 9.1中具有相同列类型int
的表继承具有类型bigint
的列的表?
如果第一个表不是选项,则将列类型更改为bigint
。
我有一个包含数千个条目的表,其ID为int。现在,ID正在慢慢接近2 ^ 32,我在想是否使用bigint ID创建一个Facade表是合理的,让原始ID继承外观。它有意义吗?
答案 0 :(得分:5)
不,当您从表中继承时,无法更改父表的列类型。
列类型必须匹配,因为当您查询父表(在ONLY
子句中没有FROM
)时,PostgreSQL也会隐式扫描子表并附加其结果。如果类型不同,它就不能这样做,就像你可以UNION
不同类型的表一样。
根据评论进行更新:
DO INSTEAD
触发器我建议使用一个视图,它是两个表的联合,旧表的内容被上传到bigint
。定义INSTEAD OF
触发器,将INSERT
重定向到新表。
如果您执行UPDATE
和DELETE
,则应该在每个表上定义CHECK
约束,将ID的范围限制为非重叠范围,然后决定哪个表根据ID路由DELETE
或UPDATE
。
对于UPDATE
,您甚至可以将其转换为DELETE ... RETURNING
和INSERT
(可能在wCTE中),以将行从旧表格移动到新表格作为更新。
会因此而导致性能下降,但您将无需进行全表重写。
你说更改密钥类型不是一个选项,但你真正想要的是"以一种需要在独占锁下重写完整表的方式更改密钥类型不是选项"
可以做的是:
ALTER TABLE ... ADD COLUMN new_key bigint;
。请不将其标记为NOT NULL
或将其设为DEFAULT
BEFORE INSERT OR UPDATE ... BEFORE EACH ROW ...
触发器,将整数ID列复制到bigint id列,例如NEW.new_id := NEW.id
UPDATE
将整数键复制到bigint列,并在每批后复制VACUUM
create unique index ... concurrently
在其上创建一个唯一索引。not null
约束。不幸的是,这将进行顺序扫描以验证约束。如果你不能容忍,那么就有黑客可以解决这个问题,但是我并不准备在公共场合为他们提供建议,因为你需要知道完全你所做的事情。要做得安全,并在适当的情况下使用它。begin
一个事务,drop
触发器,drop
旧主键约束和旧id
列,并在bigint键上添加新的主键约束,指定您同时创建的现有索引作为约束索引,然后commit
。这样就无需在独占锁下构建索引。如果PostgreSQL支持将not null
约束添加为not valid
,则此过程会更好,然后让您使用较弱的锁来验证它。不幸的是,它还没有这样做。欢迎补丁或其他贡献。
对于PostgreSQL 9.5上的某些操作,alter table
使用较弱的锁会使您受益匪浅。
从理论上讲,PostgreSQL可以通过在幕后完成所有这些来支持alter table ... alter type ... concurrently
。尽管如此,正确地做了很多的工作,所以我不希望在不久的将来看到一个简单的罐头方法。