【问题标题】:PL/SQL - Trigger only to be called on success of previous triggerPL/SQL - 仅在前一个触发器成功时调用触发器
【发布时间】:2015-03-13 05:39:57
【问题描述】:

在我正在创建的数据库中,我有两个触发器,它们都在表 Child 上的 BEFORE INSERT 上触发。

第一个触发器检查尝试插入的Child_Birthday 值是否最多为今天;因此,如果值为明天,触发器将引发用户定义的异常。

第二个触发器在第一个触发器之后触发,它将为插入的记录创建一个自定义 ID 值。

但是,在测试触发器并插入明天的日期(即15-JAN-15)时,该行仍然插入到表中。我认为这是因为第二个触发器仍然触发并插入记录,而不管第一个触发器引发异常(如果我在这里错了,请纠正我)。

我想要的是第二个触发器只有在第一个触发器没有引发异常时才会触发。

第一次触发:

create or replace TRIGGER BirthdayCheck
BEFORE INSERT ON Child
FOR EACH ROW
DECLARE
  dateError EXCEPTION;
BEGIN
  IF :NEW.Child_Birthday > SYSDATE
  THEN
    RAISE dateError;
  END IF;

  EXCEPTION
    WHEN dateError
    THEN
      DBMS_OUTPUT.PUT_LINE('ERROR: YOU HAVE ATTEMPTED TO INSERT A FUTURE DATE');
END;

第二次触发:

create or replace TRIGGER ChildID
BEFORE INSERT ON Child
FOR EACH ROW
FOLLOWS BirthdayCheck
DECLARE
  v_SeqNo INT;
  v_SubSurname CHAR(3);
  v_SeqChar VARCHAR(3);
BEGIN
  v_SeqNo := childid_sequence.nextval;
  v_SubSurname := UPPER(SUBSTR(:NEW.Child_Surname,1,3));
  v_SeqChar := TO_CHAR(v_SeqNo);

  IF v_SeqNo < 10
  THEN
    :NEW.ChildID := 'CH' || v_SubSurname || '00' || v_SeqChar;
  ELSIF v_SeqNo >= 10 AND v_SeqNo < 100
  ...
END;

【问题讨论】:

  • 最好将这些触发器组合成一个触发器。

标签: plsql triggers oracle11g


【解决方案1】:

第一个触发器引发异常。您正在捕获错误,显示一条消息(如果客户端配置为显示您不能依赖的 dbms_output 消息),然后...异常已被压扁,所以插入继续。

也许您想提出自己的异常;实际上,您说您正在引发用户定义的异常,而实际上并非如此。你宣布并举起一个,但随后将其压扁。你想做这样的事情:

create or replace TRIGGER BirthdayCheck
BEFORE INSERT ON Child
FOR EACH ROW
BEGIN
  IF :NEW.Child_Birthday > SYSDATE
  THEN
    RAISE_APPLICATION_ERROR(-20000,
      'YOU HAVE ATTEMPTED TO INSERT A FUTURE DATE');
  END IF;
END;

Read more about rasing an exception back to the caller.

【讨论】:

  • 嗯,我阅读的教程并不清楚。事实证明,我实际上是在捕获一个错误,而实际上它更像是告诉用户他们在 if else 语句中做错了什么。您的回答解决了这个问题,谢谢:)
猜你喜欢
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
  • 2018-04-01
  • 2017-09-14
  • 2021-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多