PL/SQL 触发器在插入语句之前检查值
Posted
技术标签:
【中文标题】PL/SQL 触发器在插入语句之前检查值【英文标题】:PL/SQL Trigger to check value before insert statement 【发布时间】:2021-03-17 17:14:38 【问题描述】:我是 PL/SQL 的新手,我在尝试实现的触发器方面遇到问题。
触发器的目的是在插入表之前检查货币值,以查看是否有人在插入过程中出错。如果有,他们将收到一条消息,说明该值不正确。这些值以十亿为单位,所以现在我只是检查输入的值是否高于 10000。
我目前拥有的触发器是;
CREATE TRIGGER Check_Value
BEFORE INSERT OR UPDATE OF "Potential Annual Value By 2026" ON AIPOTENTIALVALUEFORHEALTHCARE
BEGIN
IF (NEW."Potential Annual Value By 2026" < 10000.00) THEN
DBMS_OUTPUT.put_line('Value typed was incorrect');
ELSIF (NEW."Potential Annual Value By 2026" >= 10000.00) THEN
INSERT INTO AIPOTENTIALVALUEFORHEALTHCARE VALUES(NEW.ValueID, NEW.ApplicationID, NEW."Application Name", NEW.KeyDriverForAdoptionID, NEW."KeyDriverDescription", NEW."Potential Annual Value By 2026");
END IF;
END;
由于错误,这将不起作用:
PLS-00201: identifier NEW.'Potential Annual Value By 2026' must be declared
我的猜测是我错误地设置了触发器,并且它不知道在运行触发器时要检查哪个值。根据一些研究,我尝试使用 .NEW 将语句的值传递到触发器中,但是我不确定这是否是正确的实现。
我已经尝试过已经发布的方法;
CREATE TRIGGER Check_Value
BEFORE INSERT OR UPDATE OF "Potential Annual Value By 2026" ON AIPOTENTIALVALUEFORHEALTHCARE
BEGIN
IF (:NEW."Potential Annual Value By 2026" < 10000.00) THEN
DBMS_OUTPUT.put_line('Value typed was incorrect');
ELSIF (:NEW."Potential Annual Value By 2026" >= 10000.00) THEN
INSERT INTO AIPOTENTIALVALUEFORHEALTHCARE VALUES
(:NEW.ValueID, :NEW.ApplicationID, :NEW."Application Name",
:NEW.KeyDriverForAdoptionID, :NEW."KeyDriverDescription",
:NEW."Potential Annual Value By 2026");
END IF;
END;
并收到另一个错误:
ORA-04082: NEW or OLD references not allowed in table level triggers
04082. 00000 - "NEW or OLD references not allowed in table level triggers"
*Cause: The trigger is accessing "new" or "old" values in a table trigger.
*Action: Remove any new or old references.
如果此错误表明我不能在表级触发器中使用 NEW 引用,我如何能够在插入语句提交之前验证它的内容?
【问题讨论】:
顺便说一句,你真的,真的,REALLY不想在混合大小写的情况下命名列或任何其他对象或嵌入空格(更新“到 2026 年的潜在年度价值”)。每当您发现自己必须用双引号将对象名称括起来时,您都需要重新考虑。然后再次。又一次。 【参考方案1】:NEW
关键字和 FOR EACH ROW 子句之前缺少冒号。此外,您不需要(也不得)在触发器中重新发出 INSERT,无论如何都会发生(如果没有引发错误):
CREATE TRIGGER Check_Value
BEFORE INSERT OR UPDATE OF "Potential Annual Value By 2026" ON AIPOTENTIALVALUEFORHEALTHCARE
FOR EACH ROW
BEGIN
IF (:NEW."Potential Annual Value By 2026" < 10000.00) THEN
RAISE_APPLICATION_ERROR(-20001, 'Value typed was incorrect');
END IF;
END;
我确定这只是一个训练示例,但 DBMS_OUTPUT.PUT_LINE 不是向用户提出错误的合适方法,因为它的输出只能在使用 SQL Developer 等开发工具时看到。使用RAISE_APPLICATION_ERROR
。而且它实际上并没有引发异常,所以它根本不会阻止插入。
事实上,使用 CHECK 约束可能会更好地完成此检查 - 假设列值决不能低于 10000:
ALTER TABLE AIPOTENTIALVALUEFORHEALTHCARE
ADD CONSTRAINT AIPOTENTIALVALUEFORHEALTHCARE_CHK_VALUE
CHECK ("Potential Annual Value By 2026" >= 10000);
【讨论】:
我应该提到我已经尝试过这种方法但它不起作用,我将使用收到的错误编辑帖子。是的,这只是为了我自己的兴趣与 Oracle SQL Developer 的一个小游戏,但我会研究 Raise_Application_Error。 @JohnSortley24 答案已更新 - 每行都需要 谢谢,我认为 FOR EACH ROW 用于循环遍历表中的每一行,这就是我没有包含它的原因。您的逻辑对此要好得多,下次我会牢记插入语句。如果将检查约束添加到要验证的每个字段,是否可以自定义如果不满足条件会引发什么错误?从理论上讲,我可以将约束命名为错误消息,对吗?或者有没有更好的方法 使用check constraint 是可行的方法,如果违反,您将收到异常“ORA-02290:检查约束”,后跟方案名称和约束名称。见fiddle以上是关于PL/SQL 触发器在插入语句之前检查值的主要内容,如果未能解决你的问题,请参考以下文章
在使用 Entity Framework 数据库优先在表上插入行之前,如何从 PL/SQL 执行触发器?