我的任务是在订单表
时创建插入日志表的触发器还要在周五下午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外键。
答案 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
也会失败。如果明确列出列,则触发器将继续工作。如果未明确列出列,则发现将数据插入错误列的错误也相对较难。我猜到列是什么 - 你必须用正确的列名替换。