postgres 11+如何在删除默认值后保持默认值?

How does postgres 11+ maintain default value after the default is dropped?

给定以下命令:

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+ 开始,它会延迟计算 not null 默认值,这怎么可能?

列默认值存储在系统目录 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 table foo add column bar integer not null default 10

这将添加新列,并且由于 not null default 10,每行的列值都被赋予 10

此时,所有 existing 行都有 10 并且所有 future 行将被赋予 10如果插入时未提供值。

alter table foo alter column bar drop default

这不会影响现有行。它只影响 未来 插入的行,现在 需要 一个值,因为约束 not null 仍然存在,但默认值没有。