要在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可以有多个地址),非常抱歉。那是我的错。我没有解释我对这个问题的看法。每个人可以有多个地址,但只有一个默认地址。因此,当一个人将一个特定地址标记为默认地址时,其他地址必须为零;正是复合触发器修复了变异表问题。我编辑了答案并添加了示例。请看一看,非常感谢!