SET约束所有延迟,无法正常工作

问题描述 投票:12回答:1

在PostgreSQL 9.3数据库中,如果我按以下方式定义表ab

CREATE TABLE a(i integer);
ALTER TABLE a ADD CONSTRAINT pkey_a PRIMARY KEY (i);
CREATE TABLE b(j integer);
ALTER TABLE b add CONSTRAINT fkey_ij FOREIGN KEY (j)
      REFERENCES a (i) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE;
INSERT INTO a(i) VALUES(1);

然后执行以下操作:

START TRANSACTION;
SET CONSTRAINTS ALL DEFERRED;
INSERT INTO b(j) VALUES(2);
INSERT INTO a(i) VALUES(2);
COMMIT;

它会产生以下错误。为什么SET CONSTRAINTS效果不理想?

ERROR: insert or update on table "b" violates foreign key constraint "fkey_ij"
SQL state: 23503 Detail: Key (j)=(2) is not present in table "a".
sql postgresql database-design foreign-keys referential-integrity
1个回答
12
投票

DEFERRABLE约束可以延迟。

让我先提出更好的选择:

1。 INSERT顺序

反转INSERT语句的顺序,无需延迟任何操作。最简单,最快-可能的话。

2。单个命令

单个命令]执行。然后,仍然不需要推迟任何操作,因为检查了[[每个命令后]]的非延迟约束,并且将CTE视为单个命令的一部分:WITH ins1 AS ( INSERT INTO b(j) VALUES(2) ) INSERT INTO a(i) VALUES(2);

同时,您可以重用第一个INSERT的值;对于某些情况或多行插入,更安全/更方便:

WITH ins1 AS ( INSERT INTO b(j) VALUES(3) RETURNING j ) INSERT INTO a(i) SELECT j FROM ins1;

但是我需要推迟约束! (真的吗?)

ALTER TABLE b ADD CONSTRAINT fkey_ij FOREIGN KEY (j) REFERENCES a (i) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE; -- !!!

然后您的原始代码有效(速度较慢,因为延迟的约束会增加成本)。

db <>小提琴here

相关:

但是那是令人误解的,因为它仅适用于“引用动作”,即,ON UPDATEON DELETE对被引用表中的行会发生什么。当前的情况不是其中一种-如@zer0hedge pointed out

© www.soinside.com 2019 - 2024. All rights reserved.