pl / sql触发器完整性约束问题

时间:2012-05-17 20:39:17

标签: oracle plsql triggers oracle11g

我的任务是在订单表

时创建插入日志表的触发器
  1. 插入
  2. 更新
  3. 还要在周五下午5点到周一上午9点​​之间禁用插入/删除/更新。下面的解决方案涵盖了所有这些,但是因为它是一个触发器之前我不得不关闭完整性约束(这对日志表有用吗?)

    有没有人有任何建议我如何能够做到这一点并保持完整性限制(在logono列上)?

    我正在考虑使用11G compunt触发器,但是在之前的回答中它被认为这不适合使用,加上向后兼容性的问题。

       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值尚未插入到订单表中,因为这是一个之前的触发器,因此违反了logono外键。

1 个答案:

答案 0 :(得分:2)

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

您可以使触发器成为AFTER INSERT触发器,以便在ORDERS中的数据已存在之后执行触发器,以便您可以在ORDER_LOG中创建引用ONO的外键约束密钥在ORDERS。但是,想要创建这种约束似乎很奇怪。如果您将日志表创建为基表的子项,那将意味着您永远无法从ORDERS中删除行,因为总会有子行,或者您需要在执行删除之前删除ORDER_LOG的{​​{1}}的所有行。这些都不是特别理想的 - 通常,拥有日志表的关键是它将记录所有操作,而不仅仅是基表中仍然存在的行上的操作。

ONO

虽然在没有列出要插入的列的情况下在表中执行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也会失败。如果明确列出列,则触发器将继续工作。如果未明确列出列,则发现将数据插入错误列的错误也相对较难。我猜到列是什么 - 你必须用正确的列名替换。