为啥在使用`with`时会延迟`not deferable`约束?

Posted

技术标签:

【中文标题】为啥在使用`with`时会延迟`not deferable`约束?【英文标题】:Why `not deferrable` constraint is deferred when using `with`?为什么在使用`with`时会延迟`not deferable`约束? 【发布时间】:2021-05-03 14:04:24 【问题描述】:
create table T1 (
    id bigint NOT NULL primary key,
    a bigint unique not null
);
create table T2 (
    id int not null primary key,
    b bigint,
    foreign KEY(id) references T1(id) not deferrable
);
alter table T1 add constraint fk_id foreign key (id) references T2(id) not deferrable;    

--Statement 1
with ins as (
        insert into T1(id, a) values(15, 4) returning id
)
insert into T2(id, b) values(15, 3);

--Statement 2
with ins as (
        insert into T2(id, b) values(14, 4) returning id
)
insert into T1(id, a) values(14, 3);

--Statement 3 (gives error)
with upd as (
        update T1 set a = 4 where id = 14 returning id
)
update T1 set a = 3 where id = 15;

当这个脚本在 PostgreSQL 中运行时,为什么语句 1 和 2 有效,而只有语句 3 给出了错误,即使两个外键约束都明确不可延迟?

【问题讨论】:

【参考方案1】:

根据the docs 对每一行检查不可延迟的唯一约束,这与仅在语句末尾检查它们的标准规范相反。

当 UNIQUE 或 PRIMARY KEY 约束不可延迟时,PostgreSQL 会在插入或修改行时立即检查唯一性。 SQL 标准规定,唯一性应仅在语句末尾强制执行...

但是标准规范的这个例外只是为了唯一性,而不是外键。如果外键约束是不可延迟的,或者它们是可延迟的但不是延迟的,则在语句末尾检查外键约束。由于前两个示例中的语句结束时所有问题都已解决,因此没有错误。

【讨论】:

以上是关于为啥在使用`with`时会延迟`not deferable`约束?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 superview-with-subview 在模态显示(使用自动布局)时会缩小?

为啥在呈现这个模态视图时会有延迟?

为啥直播推文时会有延迟?

Go defer

为啥 MediaPlayer 在创建它的实例时会抛出 NOT present 错误?

为啥我的输入通过管道发送到进程时会延迟?