【问题标题】:Prevent Insert Trigger防止插入触发器
【发布时间】:2017-04-26 20:26:42
【问题描述】:

如何获得此触发器以防止提前不大于 0 或小于 100 的插入?谢谢。

DROP TRIGGER CheckAdvance;
CREATE OR REPLACE TRIGGER CheckAdvance
BEFORE INSERT OR UPDATE OF advance ON titles
FOR EACH ROW
WHEN (new.advance<0 OR new.advance>100)
BEGIN
dbms_output.put_line('Advance is Invalid.');
END;

【问题讨论】:

  • 触发器不能改变插入实际发生的事实。为此,为什么不在插入查询中使用一个健康的 WHERE 子句?
  • 如果这是一个设计问题,Tim 上面的评论和@GordonLinoff 在下面的回答都很出色。但是,如果这是一项课堂作业(课堂作业经常要求学生做不应该做的事情,显然是因为教授这些课程的人从来没有花足够的时间作为开发人员来了解好坏),您可以在触发器,在代码主体中捕获它,并ROLLBACK 事务,从而防止插入。请注意,这是不好的做法。
  • @BobJarvis 是的,这是一个课堂问题。我想可能和RAISE_APPLICATION_ERROR有关。
  • 是的,这听起来像教练正在寻找的东西。请记住,这是一个坏主意 - 仅仅因为您抛出异常并不意味着事务将被回滚(尽管我相信如果异常未处理,这是默认行为)。

标签: oracle plsql database-trigger


【解决方案1】:

“这是一道课堂题。”

我在一次会议上发表演讲后,与一位教授 PL/SQL 的大学讲师进行了交谈。我的演讲是关于 PL/SQL 的良好实践;我的一张幻灯片简单地说“不要使用触发器”。讲师告诉我,他发现这样的建议很难与课程的需要相协调。他们必须教他们的学生所有语法,但他承认,他们经常设置的任务要求我们在专业编写软件时不会使用的解决方案。

这是一个这样的问题。正确的方法是使用检查约束,如Gordon's answer shows。约束更有效,也更惯用。但是你的老师要你写一个触发器,所以这里是你的代码,更正了。

CREATE OR REPLACE TRIGGER CheckAdvance
    BEFORE INSERT OR UPDATE OF advance ON titles
    FOR EACH ROW
BEGIN
    IF (:new.advance < 0  
         OR :new.advance > 100)
    THEN
        raise_application_error(-20000
                , 'Advance cannot be less than zero or greater than one hundred.');
    END IF;
END;

注意事项:

  1. CREATE OR REPLACE 意味着我们可以在没有初步 DROP 语句的情况下更改触发器代码。
  2. BEGIN 和 END 帧代码块,例如触发器主体。
  3. 静态条件用 IF ... END IF 关键字框定; WHEN 用于退出循环结构。
  4. 使用 :NEW(和 :OLD)关键字引用表列值 - 注意冒号。
  5. 使用 RAISE_APPLICATION_ERROR 抛出异常;错误号必须在 -20999 到 -20000 的范围内,Oracle 为用户定义的异常保留。
  6. 让您的错误信息有意义:告诉您的用户他们做错了什么,而不是让他们猜测。
  7. 学习使用缩进使您的代码可读。您未来的同事会为此感谢您。

【讨论】:

【解决方案2】:

您不应该为此使用触发器。 Oracle(以及一般的 SQL)支持检查约束:

alter table titles
    add constraint chk_titles_advance check (advance > 0 and advance <= 100);

【讨论】:

    猜你喜欢
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 2021-09-25
    • 2013-10-12
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多