hen*_*ald 1 sql database oracle triggers constraints
嗨,我无法正确获取我的sql语法.我想创建一个查看新添加的外键的唯一约束,查看新关联实体的某些属性以确定是否允许该关系.
CREATE or replace TRIGGER "New_Trigger"
AFTER INSERT OR UPDATE ON "Table_1"
FOR EACH ROW
BEGIN
Select "Table_2"."number"
(CASE "Table_2"."number" > 0
THEN RAISE_APPLICATION_ERROR(-20000, 'this is not allowed');
END)
from "Table_1"
WHERE "Table_2"."ID" = :new.FK_Table_2_ID
END;
Run Code Online (Sandbox Code Playgroud)
编辑:APC答案非常全面,但是让我觉得我以错误的方式做到了.
情况是我有一个具有不同权限级别的人员表,我想检查这些权限级别,例如,用户"Bob"具有低级别权限,并且他试图成为需要高权限的部门主管,因此系统防止这种情况发生.
有一个后续问题,它提出了一个相关的场景,但有不同的数据模型. 在这里找到它.
因此,您要强制执行的规则是,如果TABLE_2中的某些列为零或更少,则TABLE_1只能引用TABLE_2.嗯....让我们理清触发逻辑然后我们将讨论规则.
触发器应如下所示:
CREATE or replace TRIGGER "New_Trigger"
AFTER INSERT OR UPDATE ON "Table_1"
FOR EACH ROW
declare
n "Table_2"."number".type%;
BEGIN
Select "Table_2"."number"
into n
from "Table_2"
WHERE "Table_2"."ID" = :new.FK_Table_2_ID;
if n > 0
THEN RAISE_APPLICATION_ERROR(-20000, 'this is not allowed');
end if;
END;
Run Code Online (Sandbox Code Playgroud)
请注意,您的错误消息应包含一些有用的信息,例如TABLE_1主键的值,用于在表上插入或更新多行时.
你在这里要做的是强制执行一种称为ASSERTION的约束.断言在ANSI标准中指定,但Oracle尚未实现它们.也没有任何其他RDBMS.
断言是有问题的,因为它们是对称的.也就是说,规则也需要在TABLE_2上强制执行.当您在TABLE_1中创建记录时检查规则.假设稍后某个用户更新了TABLE_2.NUMBER,因此它大于零:您的规则现在已经中断,但是在有人在TABLE_1上发出完全不相关的 UPDATE之后,您将不会知道它已被破坏,然后失败.呸.
那么该怎么办?
如果规则是实际的
如果TABLE_2.NUMBER为零,则TABLE_1只能引用TABLE_2
然后你可以在没有触发器的情况下执行它
但是,如果规则真的是我在顶部制定它,即
如果TABLE_2.NUMBER不大于零,则TABLE_1只能引用TABLE_2(即负值可以)
那么你需要另一个触发器,这次是在TABLE_2上,在规则的另一面强制执行它.
CREATE or replace TRIGGER "Assertion_Trigger"
BEFORE UPDATE of "number" ON "Table_2"
FOR EACH ROW
declare
x pls_integer;
BEGIN
if :new."number" > 0
then
begin
Select 1
into x
from "Table_1"
WHERE "Table_1"."FK_Table_2_ID" = :new.ID
and rownum = 1;
RAISE_APPLICATION_ERROR(-20001, :new.ID
||' has dependent records in Table_1');
exception
when no_data_found then
null; -- this is what we want
end;
END;
Run Code Online (Sandbox Code Playgroud)
如果TABLE_2中的记录引用了TABLE_2.NUMBER,则此触发器将不允许您将TABLE_2.NUMBER更新为大于零的值.它仅在UPDATE语句触及TABLE_2.NUMBER时触发,以最小化执行查找的性能影响.