我有一个表,其id为自动递增的主键和另一个id。
CREATE TABLE tester (
"id" integer PRIMARY KEY AUTOINCREMENT,
"refId" integer DEFAULT 0
);
如果refId> refId 应该可以是0(默认值)或参考 id 0(即充当外键)。
现在我需要两个约束:
- 如果 id 的 id 未被任何其他行 refId
使用(引用?),则该行只能删除- 如果 refId 为0,则只能删除行。
醇>
根据我的理解,我需要创建一个触发器,在DELETE事件发生之前检查这些约束。并且取决于 refId 的值,可以中止删除操作或允许删除操作。
但是,我很难理解其语法以及如何进行条件检查。但到目前为止我(记住!)关注1。):
CREATE TRIGGER no_delete_if_inuse
BEFORE DELETE ON tester
FOR EACH ROW BEGIN
SELECT RAISE(ABORT, 'cannot delete because of foreign key violation')
WHERE (SELECT "refId" FROM tester WHERE "refId" = OLD."id") IS NOT NULL;
END;
关于2。)
CREATE TRIGGER no_delete_if_ref
BEFORE DELETE ON tester
FOR EACH ROW BEGIN
IF OLD."refId" > 0 THEN RAISE(ABORT, "cannot delete tester because it refers to an existing tester");
END;
这是否有意义且有效? 我完全不确定,对我来说它确实很好,我都是菜鸟。
另外作为最后一个问题,我可以将它组合成一个触发器吗?例如,这是一个有效的查询:
CREATE TRIGGER no_delete_if_inuse
BEFORE DELETE ON tester
FOR EACH ROW BEGIN
SELECT RAISE(ABORT, 'cannot delete because of foreign key violation')
WHERE (SELECT "refId" FROM tester WHERE ("refId" = OLD."id" OR "refId" > 0) ) IS NOT NULL;
END;
答案 0 :(得分:0)
您可以定义引用同一个表的外键。对于没有引用的行,请使用null
代替0
:
create table tester(
id int primary key,
refid int references tester,
check (id <> refid)
);
insert into tester values
(1, null),
(2, null),
(3, 1),
(4, 3);
您需要一个触发器来确保无法删除引用另一行的行。
create or replace function before_delete_on_tester()
returns trigger language plpgsql as $$
begin
if old.refid is not null then
raise exception
'Cannot delete: (id)=(%) references (id)=(%)', old.id, old.refid;
end if;
return old;
end $$;
create trigger before_delete_on_tester
before delete on tester
for row execute procedure before_delete_on_tester();
测试:
delete from tester where id = 1;
ERROR: update or delete on table "tester" violates foreign key constraint "tester_refid_fkey" on table "tester"
DETAIL: Key (id)=(1) is still referenced from table "tester".
delete from tester where id = 4;
ERROR: Cannot delete from tester. (id)=(4) references (id)=(3)
CONTEXT: PL/pgSQL function before_delete_on_tester() line 4 at RAISE
在Postgres中你必须定义一个触发器功能。阅读更多: