防止插入触发器

Prevent Insert Trigger

如何获取此触发器以防止在advance 不大于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;

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

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

"it was a class question."

我在一次会议上作了演讲后,与教 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 
    THEN
        raise_application_error(-20000
                , 'Advance cannot be less than zero');
    ELSIF :new.advance > 100
    THEN
        raise_application_error(-20001
                , 'Advance cannot be greater than one hundred.');
    END IF;
END;

注意事项:

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

@yadipp 提醒我,搜索者问题中使用的 WHEN 子句是有效的语法,所以我迟早要扩展我的解决方案以展示它的外观。需要注意的最重要的一点是 NEW 和 OLD 不被视为绑定变量,因此不要使用 :.

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
    raise_application_error(-20000
                , 'Advance cannot be less than zero or greater than one hundred.');
END;

(我调整了我的原始解决方案以显示在触发器主体中使用 IF 的一个原因:以不同方式处理不同的条件。)