PL/SQL 触发完整性约束问题



我的任务是创建触发器,以便在订单表出现时插入到日志表中

  1. 插入
  2. 更新

此外,在周五下午 5 点至周一上午 9 点之间禁用插入/删除/更新。下面的解决方案涵盖了所有这些,但是因为它是之前的触发器,我不得不关闭完整性约束(这对日志表有关系吗?

有没有人对我如何做到这一点并保持完整性约束(在 logono 列上(有任何建议?

我在考虑 11G 组件触发器,但在之前的回答中有人认为这不是一个合适的用途,再加上向后兼容性的问题。

   CREATE OR REPLACE TRIGGER log_order
BEFORE INSERT OR UPDATE OR DELETE ON orders
FOR EACH ROW
DECLARE out_of_hours EXCEPTION;
BEGIN
IF INSERTING THEN
IF
 TO_NUMBER( TO_CHAR( SYSDATE, 'DHH24' ) ) BETWEEN 109 AND 517 THEN 

    insert into order_log values
 (order_log_PK.nextval, 
 (select user from dual), 
 :NEW.ono, 
 (select  SYSDATE from dual), 
 'Order Inserted' ) ;
ELSE
    RAISE out_of_hours;
END IF;
END IF;
IF UPDATING THEN 
IF
 TO_NUMBER( TO_CHAR( SYSDATE, 'DHH24' ) ) BETWEEN 109 AND 517 THEN 

    insert into order_log values
 (order_log_PK.nextval, 
 (select user from dual), 
 :NEW.ono, 
 (select  SYSDATE from dual), 
 'order updated' ) ;
ELSE
    RAISE out_of_hours;
END IF;
END IF;
IF DELETING THEN
IF 
 TO_NUMBER( TO_CHAR( SYSDATE, 'DHH24' ) ) BETWEEN 109 AND 517
 THEN 
RAISE out_of_hourS;
END IF;
END IF;
EXCEPTION 
    WHEN out_of_hours THEN
    dbms_output.put_line('there is not privelages at this time');
    RAISE_APPLICATION_ERROR(-20001, 'CANNOT UPDATE OUT OF HOURS');
END;

谢谢

编辑

完整性问题是由于进入日志表的 :NEW.ono 值尚未插入到订单表中,因为这是 before 触发器,因此违反了 logono 外键。

您可以简化触发器,以便只检查一次星期一上午 9 点 - 星期五下午 5 点的条件,以便您只有一个插入到日志表中的位置,并且无需额外的异常和异常处理程序。

可以将触发器设置为"插入后"触发器,以便触发器在ORDERS中已存在数据后执行,以便可以在ORDER_LOG中创建引用ORDERSONO键的外键约束。 但是,想要创建这种约束似乎很奇怪。 如果将日志表创建为基表的子表,则意味着您将永远无法从 ORDERS 中删除行,因为总会有一个子行,或者您需要在执行删除之前删除该ONO ORDER_LOG中的所有行。 这些通常都不是特别可取的 - 通常,拥有日志表的要点是它将记录所有操作,而不仅仅是对基表中仍然存在的行的操作。

CREATE OR REPLACE TRIGGER log_order
  AFTER INSERT OR UPDATE OR DELETE ON orders
  FOR EACH ROW
DECLARE 
  l_operation varchar2(30);
BEGIN
  if to_number( to_char( sysdate, 'ddhh24' ) ) between 109 and 517
  then
    if inserting
    then
      l_operation := 'Order inserted';
    elsif updating
    then
      l_operation := 'Order updated';
    end if;
    -- Note that I'm guessing at the names of the columns in order_log
    insert into order_log( order_log_pk, 
                           modify_user,
                           ono,
                           modify_date,
                           description )
      values( order_log_PK.nextval,
              user,
              :new.ono,
              sysdate,
              l_operation );
  else 
    raise_application_error( -20001, 'Cannot update out of hours' );
  end if;
END;

虽然在不列出要插入的列的情况下对表进行INSERT可能在语法上有效,但这样做很危险。 如果将来添加另一列,即使不需要,INSERT也会开始失败。 如果显式列出列,触发器将继续工作。 如果您没有明确列出列,则也很难发现数据插入错误列的错误。 我猜到了列是什么 - 你必须替换正确的列名。

最新更新