Oracle在触发器更新中获取更新记录的id

时间:2018-03-03 19:53:42

标签: oracle oracle11g

我有以下触发更新操作。

CREATE OR REPLACE TRIGGER oferta_trigger
  BEFORE UPDATE ON oferty
  FOR EACH ROW
DECLARE
  id_oferta     number (10);
  id_komis      number (10);
  id_test_komis number (10);
  suma          decimal(10,2) :=0;

  CURSOR c1 IS
    SELECT cena_aktualna, id_test_komis
      FROM oferty
      WHERE status = 'A';
BEGIN
  id_oferta := :NEW.idk;
  dbms_output.put_line(id_oferta);

  SELECT komis_id INTO id_komis FROM oferty WHERE idk = id_oferta;

  FOR i in c1 LOOP
    IF i.id_test_komis = id_komis THEN
       suma := suma + i.cena_aktualna;
    END IF;
  END LOOP;

  UPDATE komisy SET wartosc_samochodow = suma WHERE idk = id_komis;
END;

在更新操作期间。

UPDATE oferty SET status ='Z' WHERE idk =1;

我收到以下错误:

  

SQL错误:ORA-04091:表OFERTY正在变异,触发器/函数可能   看不到它。

如何解决问题。我认为这是获得身份证的问题。

1 个答案:

答案 0 :(得分:3)

以下是基于Scott模式的示例。我更改了DEPT表,添加了一个新列(SUM_SAL),该列应该包含该部门所有工资的总和。

首先,好的,旧的变异表方式。

SQL> create or replace trigger trg_sumsal
  2    after update on emp
  3    for each row
  4  declare
  5    l_sum number;
  6  begin
  7    select sum(sal) into l_sum
  8      from emp
  9      where empno = :new.empno;
 10
 11    update dept set sum_sal = l_sum
 12      where deptno = :new.deptno;
 13  end;
 14  /

Trigger created.

SQL> update emp set sal = 5000 where ename = 'KING';
update emp set sal = 5000 where ename = 'KING'
       *
ERROR at line 1:
ORA-04091: table SCOTT.EMP is mutating, trigger/function may not see it
ORA-06512: at "SCOTT.TRG_SUMSAL", line 4
ORA-04088: error during execution of trigger 'SCOTT.TRG_SUMSAL'


SQL>

正如我们已经知道的那样,这是行不通的。

现在,复合触发器:

SQL> create or replace trigger trg_sumsal
  2    for update or insert on emp
  3    compound trigger
  4
  5    l_deptno emp.deptno%type;
  6
  7    after each row is
  8    begin
  9      l_deptno := :new.deptno;
 10    end after each row;
 11
 12    after statement is
 13      l_sum number;
 14    begin
 15      select sum(sal) into l_Sum
 16        from emp
 17        where deptno = l_deptno;
 18
 19      update dept set sum_sal = l_sum
 20      where deptno = l_deptno;
 21    end after statement;
 22  end;
 23  /

Trigger created.

SQL> update emp set sal = 10000 where ename = 'KING';

1 row updated.

SQL> select * From dept;

    DEPTNO DNAME          LOC              SUM_SAL
---------- -------------- ------------- ----------
        10 ACCOUNTING     NEW YORK           13750
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

SQL>

尼斯;这有效!

[编辑,阅读威廉的评论后]

如果在单个UPDATE语句中影响了多个部门,则上述代码将无法正常运行。略微调整,它看起来像这样&解决了这个问题:

SQL> create or replace trigger trg_sumsal
  2    for update or insert on emp
  3    compound trigger
  4
  5    type t_tab is table of number;
  6    l_tab t_tab := t_tab();
  7
  8    after each row is
  9    begin
 10      l_tab.extend;
 11      l_tab(l_tab.last) := :new.deptno;
 12    end after each row;
 13
 14    after statement is
 15      l_sum number;
 16    begin
 17      for i in l_tab.first .. l_tab.last loop
 18        select sum(sal) into l_Sum
 19          from emp
 20          where deptno = l_tab(i);
 21
 22        update dept set sum_sal = l_sum
 23          where deptno = l_tab(i);
 24      end loop;
 25    end after statement;
 26  end;
 27  /

Trigger created.

测试:

SQL> select * from dept;

    DEPTNO DNAME          LOC              SUM_SAL
---------- -------------- ------------- ----------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

SQL> update emp set sal = 10000 where ename in ('SMITH', 'KING');

2 rows updated.

SQL> select * from dept;

    DEPTNO DNAME          LOC              SUM_SAL
---------- -------------- ------------- ----------
        10 ACCOUNTING     NEW YORK           13750
        20 RESEARCH       DALLAS             15975
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

SQL>