Sql Oracle唯一约束-用于检查新关系中属性值的触发器
嗨,我的sql语法不正确。我想创建一个唯一的约束,它查看新添加的外键,查看新相关实体的一些属性,以确定是否允许这种关系Sql Oracle唯一约束-用于检查新关系中属性值的触发器,sql,database,oracle,triggers,constraints,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(-200
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;
编辑:APC的答案非常全面,但是让我觉得我做得不对
情况是,我有一个具有不同权限级别的人员表,我想检查这些权限级别,例如,用户“Bob”具有低级别权限,他试图成为需要高权限的部门主管,因此系统会防止这种情况发生
还有一个后续问题,提出了一个相关的场景,但数据模型不同 不要使用触发器创建唯一约束或外键约束。Oracle对唯一键和外键提供声明式支持,例如: 在列上添加唯一约束:
ALTER TABLE "Table_1" ADD (
CONSTRAINT table_1_uk UNIQUE (column_name)
);
添加外键关系:
ALTER TABLE "ChildTable" ADD (
CONSTRAINT my_fk FOREIGN KEY (parent_id)
REFERENCES "ParentTable" (id)
);
我不清楚你到底想用触发器实现什么-它有点混乱,SQL和PL/SQL混在一起不起作用,而且似乎引用了“Table_2”
上的一列,实际上没有被查询
一个好的经验法则是,如果您的触发器正在查询触发器所在的同一个表,那么它可能是错误的
我不确定,但你是在追求某种有条件的外键关系吗?i、 e.“仅允许父级满足条件x的子行”?如果是这样,问题就出在数据模型中,应该在那里解决。如果您提供更多关于您试图实现的目标的解释,我们应该能够帮助您。不要使用触发器来创建唯一约束或外键约束。Oracle对唯一键和外键提供声明式支持,例如: 在列上添加唯一约束:
ALTER TABLE "Table_1" ADD (
CONSTRAINT table_1_uk UNIQUE (column_name)
);
添加外键关系:
ALTER TABLE "ChildTable" ADD (
CONSTRAINT my_fk FOREIGN KEY (parent_id)
REFERENCES "ParentTable" (id)
);
我不清楚你到底想用触发器实现什么-它有点混乱,SQL和PL/SQL混在一起不起作用,而且似乎引用了“Table_2”
上的一列,实际上没有被查询
一个好的经验法则是,如果您的触发器正在查询触发器所在的同一个表,那么它可能是错误的
我不确定,但你是在追求某种有条件的外键关系吗?i、 e.“仅允许父级满足条件x的子行”?如果是这样,问题就出在数据模型中,应该在那里解决。如果您提供更多关于您试图实现的目标的解释,我们应该能够帮助您。因此,您要执行的规则是,如果表2中的某列为零或更少,则表1只能引用表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;
请注意,在插入或更新表上的多行时,错误消息应包括一些有用的信息,例如表_1主键的值
这里您要做的是强制执行一种称为断言的约束类型。断言是在ANSI标准中指定的,但Oracle尚未实现它们。任何其他关系数据库也没有达到这一点 断言是有问题的,因为它们是对称的。也就是说,还需要在表2上强制执行该规则。在表1中创建记录时检查规则的时刻。假设稍后某个时间某个用户更新了表_2.NUMBER,使其大于零:您的规则现在已被破坏,但您不会知道它已被破坏,直到有人对表_1进行了完全不相关的更新,然后更新将失败。恶心 那么,该怎么办 如果规则是 只有在以下情况下,表_1才能引用表_2 表2.1的数字为零 然后,您可以在不使用触发器的情况下强制执行它
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;
如果表_2中的记录引用了表_2.NUMBER,则此触发器将不允许您将其更新为大于零的值。它仅在UPDATE语句触及表2.NUMBER时触发,以最小化执行查找对性能的影响 因此,您要强制执行的规则是,如果表2中的某些列为零或更少,则表1只能引用表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;
请注意,在插入或更新表上的多行时,错误消息应包括一些有用的信息,例如表_1主键的值
这里您要做的是强制执行一种称为断言的约束类型。断言是在ANSI标准中指定的,但Oracle尚未实现它们。任何其他关系数据库也没有达到这一点 断言是有问题的,因为它们是对称的。也就是说,还需要在表2上强制执行该规则。在表1中创建记录时检查规则的时刻。苏