当 table 本身存在外键约束时,postgresql 多重插入如何工作?

How postgresql multiple insert works when there is foreign key constraint in the table itself?

假设我有一个 schools table

CREATE TABLE "public"."schools" (
    "id" text NOT NULL,
    "ancestor_id" text,
    CONSTRAINT "schools_ancestor_id_fkey" FOREIGN KEY ("ancestor_id") REFERENCES "public"."schools"("id"),
    PRIMARY KEY ("id")
);

我想为 schools

插入多个值
INSERT INTO schools (id, ancestor_id) VALUES ('school 1', 'ancestor 1'), ('ancestor 1', NULL)

我预计插入查询会引发外键异常,但它实际上成功插入了 2 行。

有人知道这是为什么吗?我查看了 insert 的文档,但它没有提到任何类似的情况。

外键在 语句 完成后计算,而不是在每一行之后计算。

这就是为什么在单个语句中删除它们也有效的原因:

delete from schools 
where id in ('school 1', 'ancestor 1');

外键约束是通过 PostgreSQL 中的触发器实现的。这没有直接记录,但您可以间接看到它 here:

One can disable or enable a single trigger specified by name, or all triggers on the table, or only user triggers (this option excludes internally generated constraint triggers such as those that are used to implement foreign key constraints or deferrable uniqueness and exclusion constraints).

你也可以用

看到
SELECT * FROM pg_trigger
WHERE tgrelid = 'schools'::regclass;

触发器的触发规则 are documented 也适用于外键:

Row-level BEFORE triggers fire immediately before a particular row is operated on, while row-level AFTER triggers fire at the end of the statement (but before any statement-level AFTER triggers).

(强调我的)

所以外键在完成完整的语句后才被验证。