PL/SQL - 触发器仅在前一个触发器成功时调用

PL/SQL - Trigger only to be called on success of previous trigger

在我正在创建的数据库中,我有两个触发器,它们都在 table Child.

上的 BEFORE INSERT 上触发

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

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

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

我想要的是第二个触发器仅在第一个触发器未引发异常时触发。

第一个触发器:

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;

第一个触发器不会引发异常。您正在捕获错误,显示一条消息(if 客户端配置为显示 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.