日期:2014-05-16  浏览次数:21248 次

触发器调用带有commit的存储过程
大家好!
今天遇到一个问题,很烦解决不掉!
我谢了一个触发器:
CREATE OR REPLACE TRIGGER createmyoprteq
AFTER INSERT OR UPDATE OR DELETE ON QIXIANG.OPRT_EQ
BEGIN
  proc('oprtEq','oprt_psn_division','oprt_eq_model','oprt_eq_count','myoprteq');
END;

在这个触发器中调用一个存储过程:
create or replace procedure proc(tabname in varchar2,
  col1 in varchar2,
  col2 in varchar2,
  col3 in varchar2,
  viewname in varchar2 default 'v_tmp')
as
  sqlstr varchar2(2000):='create or replace view '||viewname||' as select '||col1||' ';
  c1 sys_refcursor;
  v1 varchar2(100);
begin
  open c1 for 'select distinct to_char('||col2||') from '||tabname;
  loop
  fetch c1 into v1;
  exit when c1%notfound;
  sqlstr:=sqlstr||'
  ,max(decode('||col2||','''||v1||''','||col3||'))"'||v1||'"';
  end loop;
  close c1;
  sqlstr:=sqlstr||' from '||tabname||' group by '||col1;
  execute immediate sqlstr;
end proc;

这个存储过程是把我的一个表进行行列转换,生成一个视图!因为触发器里面不能有commit关键字,所有不能执行!
不知道有什么办法可以解决!从网上查到可以使用自治事务:我把存储过程改成如下:

create or replace procedure proc(tabname in varchar2,
  col1 in varchar2,
  col2 in varchar2,
  col3 in varchar2,
  viewname in varchar2 default 'v_tmp')
as
  PRAGMA AUTONOMOUS_TRANSACTION; //这是我加的部分!
  sqlstr varchar2(2000):='create or replace view '||viewname||' as select '||col1||' ';
  c1 sys_refcursor;
  v1 varchar2(100);

begin
  open c1 for 'select distinct to_char('||col2||') from '||tabname;
  loop
  fetch c1 into v1;
  exit when c1%notfound;
  sqlstr:=sqlstr||'
  ,max(decode('||col2||','''||v1||''','||col3||'))"'||v1||'"';
  end loop;
  close c1;
  sqlstr:=sqlstr||' from '||tabname||' group by '||col1;
  execute immediate sqlstr;
  commit;
end proc;

执行没有错误了!可是好像并不能重新生成我的视图!但是我手动执行存储过程可以生成我需要的视图。
求高手帮忙呀!

------解决方案--------------------
在这个procedure中sqlstr查询了触发器触发的表OPRT_EQ
------解决方案--------------------
CREATE OR REPLACE TRIGGER createmyoprteq 
AFTER INSERT OR UPDATE OR DELETE ON QIXIANG.OPRT_EQ 
BEGIN 
proc('oprtEq','oprt_psn_division','oprt_eq_model','oprt_eq_count','myoprteq'); 
commit;
END; 
好高兴,我的过程派上用场了~
------解决方案--------------------
我觉得是先想明白,人家触发器本身是跟外面一个事务,如果你需要另开一个事务当然就相当于约定了不会直接再修改外面的事务更新的表了。不然就很奇怪了,说不定有潜在问题呢。