日期:2014-05-17  浏览次数:21125 次

oracle 触发器 自治事务
有一个主表 wx_sheet 和子表 wx_sheetfitting 
想要创建一个触发器 当删除 子表 时 判断 主表中主表中affirmdate是否为空
 如果 空 则 提交 
否则 回滚
create or replace trigger TRG_I_DELETE before delete on wx_sheetfitting for each row
declare
  PRAGMA AUTONOMOUS_TRANSACTION;
  affirmdate1 varchar2(10);
begin
  select affirmdate
  into affirmdate1
  from wx_sheet t
  where t.sheetno = :old.sheetno;
  dbms_output.put_line(affirmdate1);
  if affirmdate1 is not null then
  rollback;
  else
  commit;
  end if;
  end;
这样写行么?

------解决方案--------------------
SQL code

--你理解有误,触发器作为事务的一部分,如果不想让delete继续执行的话
--触发器要报错才行,否则只要触发器正常执行完了,delete 就会起作用
--而且即便你触发器里面有 commit和rollback 也是针对自治事务的,跟delete没两毛钱关系
CREATE OR REPLACE TRIGGER TRG_I_DELETE
  BEFORE DELETE ON WX_SHEETFITTING
  FOR EACH ROW
DECLARE
  PRAGMA AUTONOMOUS_TRANSACTION;
  AFFIRMDATE1 VARCHAR2(10);
BEGIN
  SELECT AFFIRMDATE
    INTO AFFIRMDATE1
    FROM WX_SHEET T
   WHERE T.SHEETNO = :OLD.SHEETNO;
  --DBMS_OUTPUT.PUT_LINE(AFFIRMDATE1);
  IF AFFIRMDATE1 IS NOT NULL THEN
    raise_application_error(-20001,'主表affirmdate不为空,不允许删除字表信息!'); --ROLLBACK;
  ELSE
    NULL;--COMMIT;
  END IF;
END;

------解决方案--------------------
raise_application_error 是oracle提供的人为让oracle抛异常的方法
抛出的异常跟 oracle自己的异常效果是一样的

探讨

引用:
SQL code

--你理解有误,触发器作为事务的一部分,如果不想让delete继续执行的话
--触发器要报错才行,否则只要触发器正常执行完了,delete 就会起作用
--而且即便你触发器里面有 commit和rollback 也是针对自治事务的,跟delete没两毛钱关系
CREATE OR REPLACE TRIGGER TRG_I_DELETE
……

------解决方案--------------------
你为什么要用自治事务,自治事务不影响主事务的,也就是说你再触发器里的commit或者rollback是不会影响到你删除wx_sheetfitting 这个表的那个事务

而且如果你
select affirmdate
into affirmdate1
from wx_sheet t
where t.sheetno = :old.sheetno;
这条语句查出来的结果为空的话会出exception
必须捕获这个exception
exception 
WHEN no_data_found THEN
commit;