ON DELETE外键引用的条件逻辑

时间:2016-12-12 01:55:57

标签: sql postgresql constraints

我希望能够为外键ON DELETE约束执行一些逻辑。根据逻辑,我要么想要CASCADE或RESTRICT。

我的桌子:

CREATE TABLE users (
  user_id uuid DEFAULT uuid_generate_v4() PRIMARY KEY
);

CREATE TABLE teams (
  team_id uuid DEFAULT uuid_generate_v4() PRIMARY KEY
);

CREATE TABLE documents (
  document_id uuid DEFAULT uuid_generate_v4() PRIMARY KEY
  user_id uuid REFERENCES users ON DELETE /*do logic here*/,
  team_id uuid REFERENCES teams ON DELETE /*do logic here*/,
  content text
);

在我的(非常基本的)表格中,document和/或user可以拥有team

关于documents,如果有人删除文档的用户并且文档的team_id为空,则CASCADE删除到文档(反之亦然,用user_id和team_id)。

否则,如果有人删除了文档的用户并且文档的team_id不是NULL,则限制删除用户(反之亦然,使用user_id和team_id)。

我在文档中没有看到任何完成此操作的方法。我是否需要在服务器代码中而不是在数据库中执行此逻辑?我想要额外的数据完整层。

1 个答案:

答案 0 :(得分:2)

这很可能,但不是直接的。你需要一个触发器。首先将外键设置为RESTRICT

CREATE TABLE documents (
  document_id uuid DEFAULT uuid_generate_v4() PRIMARY KEY,
  user_id uuid REFERENCES users ON DELETE RESTRICT,
  team_id uuid REFERENCES teams ON DELETE RESTRICT,
  content text
);

然后创建触发器功能和用户表的触发器

CREATE OR REPLACE FUNCTION user_delete()
RETURNS TRIGGER AS $$
BEGIN
    DELETE FROM documents WHERE team_id IS NULL and user_id = OLD.user_id;
    RETURN OLD;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER user_delete_trigger BEFORE DELETE ON users FOR EACH ROW     EXECUTE PROCEDURE user_delete();

然后为团队表做同样的事情。

CREATE OR REPLACE FUNCTION team_delete()
RETURNS TRIGGER AS $$
BEGIN
    DELETE FROM documents WHERE user_id IS NULL and team_id = OLD.team_id;
    RETURN OLD;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER team_delete_trigger BEFORE DELETE ON users FOR EACH ROW     EXECUTE PROCEDURE team_delete();

而且我相信这正是你正在寻找的。