Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
要在Oracle中更新的触发器_Oracle_Triggers_Mutating Table - Fatal编程技术网

要在Oracle中更新的触发器

要在Oracle中更新的触发器,oracle,triggers,mutating-table,Oracle,Triggers,Mutating Table,我尝试了很多方法来创建一个触发器,在其他寄存器上更新一个字段之后更新该字段。总是失败 当我对每一行使用时会得到变异表错误。当我试图直接更新时,我不知道如何引用新值 每个人可以有多个地址,但只有一个默认地址。因此,当此人将一个特定地址标记为默认地址时,其他地址必须为零 CREATE OR REPLACE TRIGGER trg_aiur_default_address BEFORE UPDATE ON address FOR EACH ROW BEGIN UPDATE address SE

我尝试了很多方法来创建一个触发器,在其他寄存器上更新一个字段之后更新该字段。总是失败

当我对每一行使用
会得到变异表错误。当我试图直接更新时,我不知道如何引用新值

每个人可以有多个地址,但只有一个默认地址。因此,当此人将一个特定地址标记为默认地址时,其他地址必须为零

CREATE OR REPLACE TRIGGER trg_aiur_default_address
BEFORE UPDATE ON address FOR EACH ROW
BEGIN
    UPDATE address SET default_address = 0
    WHERE person_id = :NEW.id;
END;
/
ORA-04091:桌上人正在变异,触发器/函数可能看不到它

ORA-04082:表级触发器中不允许新引用或旧引用

只是

:new.cdefault := 0;  
(无法命名列
默认值
,它是保留的)


正如您所评论的那样,它将无法工作,因为您将“更新整个表”,这是胡说八道。看一看

SQL> create table person as
  2    select 1 id, 200 cdefault from dual union all
  3    select 2 id, 350 cdefault from dual;

Table created.

SQL> create or replace trigger trg_aiur_default_address
  2    before update on person
  3    for each row
  4  begin
  5      :new.cdefault := 0;
  6  end;
  7  /

Trigger created.

SQL> update person set id = 500 where id = 1;

1 row updated.

SQL> select * from person;

        ID   CDEFAULT
---------- ----------
       500          0            --> see? CDEFAULT = 0
         2        350            --> for ID = 2 nothing changed

SQL>

在你(最终)下定决心告诉我们每个人可以有多个地址后,我建议使用一个复合触发器来“修复”变异表错误

在我看来,您应该有两个表-
person
(master)和
address
(detail;包含每个人的所有地址;它有一个指向
person
表的外键)

复合触发器:

SQL> create or replace trigger trg_bu_dflt_addr
  2    for update on address
  3    compound trigger
  4
  5    type t_rec is table of address%rowtype;
  6    l_tab t_rec;
  7
  8    before statement is
  9      begin
 10        l_tab := t_rec();
 11      end before statement;
 12
 13    before each row is
 14    begin
 15      null;
 16    end before each row;
 17
 18    after each row is
 19      begin
 20        l_tab.extend;
 21        l_tab(l_tab.count()).id := :new.id;
 22        l_tab(l_tab.count()).id_pers := :new.id_pers;
 23        l_tab(l_tab.count()).cb_default := :new.cb_default;
 24      end after each row;
 25
 26    after statement is
 27      begin
 28        for i in 1 .. l_tab.count() loop
 29          if l_tab(i).cb_default = 1 then
 30             update address a set
 31               a.cb_default = 0
 32               where a.id_pers = l_tab(i).id_pers
 33                 and a.id <> l_tab(i).id;
 34          end if;
 35        end loop;
 36      end after statement;
 37  end;
 38  /

Trigger created.
只是

:new.cdefault := 0;  
(无法命名列
默认值
,它是保留的)


正如您所评论的那样,它将无法工作,因为您将“更新整个表”,这是胡说八道。看一看

SQL> create table person as
  2    select 1 id, 200 cdefault from dual union all
  3    select 2 id, 350 cdefault from dual;

Table created.

SQL> create or replace trigger trg_aiur_default_address
  2    before update on person
  3    for each row
  4  begin
  5      :new.cdefault := 0;
  6  end;
  7  /

Trigger created.

SQL> update person set id = 500 where id = 1;

1 row updated.

SQL> select * from person;

        ID   CDEFAULT
---------- ----------
       500          0            --> see? CDEFAULT = 0
         2        350            --> for ID = 2 nothing changed

SQL>

在你(最终)下定决心告诉我们每个人可以有多个地址后,我建议使用一个复合触发器来“修复”变异表错误

在我看来,您应该有两个表-
person
(master)和
address
(detail;包含每个人的所有地址;它有一个指向
person
表的外键)

复合触发器:

SQL> create or replace trigger trg_bu_dflt_addr
  2    for update on address
  3    compound trigger
  4
  5    type t_rec is table of address%rowtype;
  6    l_tab t_rec;
  7
  8    before statement is
  9      begin
 10        l_tab := t_rec();
 11      end before statement;
 12
 13    before each row is
 14    begin
 15      null;
 16    end before each row;
 17
 18    after each row is
 19      begin
 20        l_tab.extend;
 21        l_tab(l_tab.count()).id := :new.id;
 22        l_tab(l_tab.count()).id_pers := :new.id_pers;
 23        l_tab(l_tab.count()).cb_default := :new.cb_default;
 24      end after each row;
 25
 26    after statement is
 27      begin
 28        for i in 1 .. l_tab.count() loop
 29          if l_tab(i).cb_default = 1 then
 30             update address a set
 31               a.cb_default = 0
 32               where a.id_pers = l_tab(i).id_pers
 33                 and a.id <> l_tab(i).id;
 34          end if;
 35        end loop;
 36      end after statement;
 37  end;
 38  /

Trigger created.

我不能那样做。我要换整张桌子。我只想更改特定ID的默认地址(每个ID可以有多个地址),非常抱歉。那是我的错。我没有解释我对这个问题的看法。每个人可以有多个地址,但只有一个默认地址。因此,当一个人将一个特定地址标记为默认地址时,其他地址必须为零;正是复合触发器修复了变异表问题。我编辑了答案并添加了示例。请看一看,非常感谢!我不能那样做。我要换整张桌子。我只想更改特定ID的默认地址(每个ID可以有多个地址),非常抱歉。那是我的错。我没有解释我对这个问题的看法。每个人可以有多个地址,但只有一个默认地址。因此,当一个人将一个特定地址标记为默认地址时,其他地址必须为零;正是复合触发器修复了变异表问题。我编辑了答案并添加了示例。请看一看,非常感谢!