给定以下命令:
create table foo(id serial primary key);
insert into foo values (1), (2), (3), (4);
alter table foo add column bar integer not null default 10;
alter table foo alter column bar drop default;
当我执行select * from foo;
时,我得到:
id | bar
----+------
1 | 10
2 | 10
3 | 10
4 | 10
如果从 postgresql 11+ 开始,它懒惰地计算不为空的默认值,这怎么可能?
列缺省值存储在系统目录pg_attrdef
中,而列定义存储在pg_attribute
中。如果删除默认值,则会删除pg_attrdef
行,但不会删除pg_attribute
行。
您观察到的秘密是"缺少的属性值"存储在pg_attribute
中,因此不受影响:
SELECT attmissingval
FROM pg_attribute
WHERE attrelid = 'foo'::regclass
AND attname = 'bar';
attmissingval
═══════════════
{10}
(1 row)
分解每个 alter 语句:
alter table foo add column bar integer not null default 10
这将添加新列,并且由于not null default 10
,每行都为列值提供10
。
此时,所有现有行都10
,如果插入时未提供值,则将10
所有未来行。
alter table foo alter column bar drop default
这不会影响现有行。它只影响插入的未来行,现在需要一个值,因为约束not null
保留,但默认值不会。