我希望能够对删除约束上的外键执行一些逻辑。根据逻辑,我要么要级联,要么要限制。
我的桌子:
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
);
在我的(非常基本的)表中,a
document
可以由auser
和/或ateam
拥有。关于
documents
,如果有人删除了文档的用户,并且文档的team_id
为空,则将删除操作层叠到文档中(反之亦然,使用用户id和团队id)。否则,如果有人删除了文档的用户,并且文档的
team_id
不为空,则限制删除该用户(反之亦然,用户id和团队id)。我在文档中看不到任何实现这一点的方法。我需要在服务器代码中而不是数据库中执行此逻辑吗?我需要额外的数据完整性层。
最佳答案
这是完全可能的,但不是直接的。你需要一个扳机。首先设置要限制的外键
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();
我相信这正是你想要的。