我的任务是创建触发器,以便在订单表出现时插入到日志表中
- 插入
- 更新
此外,在周五下午 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
中创建引用ORDERS
中ONO
键的外键约束。 但是,想要创建这种约束似乎很奇怪。 如果将日志表创建为基表的子表,则意味着您将永远无法从 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
也会开始失败。 如果显式列出列,触发器将继续工作。 如果您没有明确列出列,则也很难发现数据插入错误列的错误。 我猜到了列是什么 - 你必须替换正确的列名。