假设存在以下表和触发器.

CREATE TABLE "parent_table"
(
    id uuid PRIMARY KEY
);

CREATE TABLE "child_table"
(
    id        bigserial PRIMARY KEY,
    parent_id uuid,
    CONSTRAINT "child_table_parent_id_fkey" FOREIGN KEY ("parent_id") REFERENCES "parent_table" ("id") ON DELETE CASCADE
);

CREATE OR REPLACE FUNCTION add_child_trigger() RETURNS TRIGGER AS
$$
BEGIN
    RETURN new;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER "on_change_add_change_event"
    BEFORE INSERT OR UPDATE OR DELETE
    ON "child_table"
    FOR EACH ROW
EXECUTE PROCEDURE "add_child_trigger"();

执行以下语句:

INSERT INTO "parent_table" VALUES ('a275b51e-9a4f-460f-a0df-589fac39f9fe');
INSERT INTO "child_table" ("parent_id") VALUES ('a275b51e-9a4f-460f-a0df-589fac39f9fe');
DELETE FROM "parent_table" WHERE "id" = 'a275b51e-9a4f-460f-a0df-589fac39f9fe';

然后请注意,显然每child_table个条目中仍然存在一个条目,但它指向一个不存在的parent_table记录.我以为外键保证了目标记录的存在,不是吗?

推荐答案

这是令人惊讶的行为,但根据this message名工作人员的预期:

CREATE FUNCTION silly() RETURNS trigger LANGUAGE plpgsql AS 'BEGIN RETURN NULL; END;';
CREATE TRIGGER silly BEFORE DELETE ON child FOR EACH ROW EXECUTE FUNCTION silly();

触发器函数取消了对"Child"的级联删除,我们只剩下 "子"中没有引用"父"中的行的行.

是.这是经过设计的:触发器的操作级别低于 外键,因此设计不周的触发器可能会 destruct FK约束. 这在某个地方有记录,尽管可能还不够明显.

我们有充分的理由希望触发器能够看到和 对FK驱动的更新做出react ,所以我们不太可能想要 重新审视那个设计决定,即使它还没有站稳脚跟 几十年来.

*问候汤姆·莱恩

Sql相关问答推荐

使用group by后我的平均输出不是我想要的

如何根据SQL中的列条件获取下一个时间戳?

Group By子句返回太多行

JSON列之间的Postgr聚合

SQL查询组类值在同一行中,并连接和排序其他值

在postgres中动态计算出现次数并插入到json中

SQL查询每个客户的最新条目

Access中执行INSERT INTO查询时出现错误消息

查询每周数据(周一至周日),避免年度日期重叠

为什么我的SQL标量函数有时会抛出";子查询返回多个值.这是不允许的.

使用generate_series()时,LEFT联接缺少日期/间隔

将时间范围划分为全天和前后剩余小时

将具有嵌套 XML 的列转换为 SQL 中的表格格式?

Grafana SQL 模板变量(值、文本)

日期逻辑(查找过go 90 天内的第一个匹配行)

SQL 查找 varchar 类型列及其值中多次出现的子字符串

Postgres数据库维护:基于GROUP BY删除旧记录

奇怪的甲骨文行为

将单行中的多个行值转换为列

使用 json_agg 从 SQL 查询获取 [null] 响应