如何调用在触发器后使用相同表的过程

时间:2014-11-23 20:10:54

标签: oracle plsql oracle11g triggers

我希望在删除以下方法失败的数据后使用相同的表数据。

我遇到的问题是在触发器完成之前,最新的更改没有得到提交。


create table test_tbl(id_ number, type_ varchar2(100) , count_ number);

create table test_count_tbl(type varchar2(100), count_ number) ; 

 begin 
    insert into test_tbl(id_ , type_  , count_ ) values (1,'type1', 10 );
    insert into test_tbl(id_ , type_  , count_ )  values (2,'type1', 20 );
    insert into test_tbl(id_ , type_  , count_ )  values (3,'type2', 10 );
    insert into test_tbl(id_ , type_  , count_ )  values (4,'type2', 40 );
    insert into test_tbl(id_ , type_  , count_ )  values (5,'type3', 10 );
    insert into test_tbl(id_ , type_  , count_ )  values (6,'type3', 60 );
    commit;
    end;

create or replace procedure test_count_update_p( p_type_ in varchar2) 
is 
begin 

  MERGE INTO test_count_tbl D
   USING (select type_, sum(count_) count_sum_
          from test_tbl
          where type_ = p_type_
          group by type_ ) S   ON (D.type = S.count_sum_)
   WHEN MATCHED THEN UPDATE SET D.count_ = S.count_sum_ 
   --  DELETE WHERE (S.salary > 8000)
   WHEN NOT MATCHED THEN INSERT (D.type, D.count_)
     VALUES (S.type_, S.count_sum_);
  commit;
end ;

 CREATE OR REPLACE TRIGGER test_tbl_trigger
    AFTER INSERT  OR DELETE OR UPDATE ON test_tbl 
    FOR EACH ROW

    DECLARE    
       PRAGMA AUTONOMOUS_TRANSACTION;    
       L_TYPE VARCHAR2(100);
    BEGIN    
        if DELETING THEN 
           L_TYPE  := :OLD.TYPE_;
           end if;

        IF UPDATING OR INSERTING THEN 
          L_TYPE  := :NEW.TYPE_;
        end if; 

       test_count_update_p(L_TYPE);    
       COMMIT;    
    END;

执行以下操作以查看确切问题..

begin 
insert into test_tbl(id_ , type_  , count_ )  values (7,'type4', 60 );
commit;
end;

select * from test_tbl ;

记录被插入到表中。

select * from test_count_tbl ; 

记录在此表中尚未计入。

begin 
delete test_tbl where id_ = 7;
commit ;
end;

select * from test_tbl ;

删除了记录。

select * from test_count_tbl ; 

计算表test_tbl;

中没有的记录

3 个答案:

答案 0 :(得分:2)

你不能。

正常的行级触发器无法查询定义触发器的表,因为这会引发变异表异常。我假设这就是为什么你声明你的触发器使用自治事务(除了持久性日志之外的任何事情的自治事务几乎肯定是一个错误)。但是,如果这样做,则触发器无法看到触发事务所做的未提交更改。这就是你现在遇到的问题。

另一种方法是使用compound trigger。您将声明一个test_table.type_%type的集合,您将在触发器的行级部分中添加更改为此集合的值,然后您将在after语句中迭代集合中的元素触发器的一部分。允许语句级触发器查询定义了触发器的表,以便可以从复合触发器的后语句部分调用过程。

答案 1 :(得分:0)

您的最佳操作是完全删除TEST_COUNT_TBL表。只需按名称创建一个视图:

create view TEST_COUNT_TBL as
select type_ Type, sum( count_ ) Count
from test_tbl
group by type_;

然后,您将始终掌握准确,最新的信息,但不必担心使用触发器做一些奇怪而美妙的事情。

答案 2 :(得分:0)

使用复合触发并删除PRAGMA AUTONOMOUS_TRANSACTION;以及删除的commit语句。仍然提交的数据可以在外部函数中访问和执行计算,并写入单独的表。