如何创建条件触发器

时间:2018-02-15 12:59:45

标签: sql postgresql sqlite triggers

我有一个表,其id为自动递增的主键和另一个id。

CREATE TABLE tester (
"id" integer PRIMARY KEY AUTOINCREMENT,
"refId" integer DEFAULT 0
);
如果refId>

refId 应该可以是0(默认值)或参考 id 0(即充当外键)。

现在我需要两个约束:

  
      
  1. 如果 id id 未被任何其他行 refId
  2. 使用(引用?),则该行只能删除   
  3. 如果 refId 为0,则只能删除行。
  4.   

根据我的理解,我需要创建一个触发器,在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;

1 个答案:

答案 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中你必须定义一个触发器功能。阅读更多: