[英]Updating the record of same table when new record is inserted or updated in oracle
I am new to learning Oracle. 我是新来学习Oracle的人。 I have a task in which I need to update value of any previous record if new record contains its reference.
我有一个任务,如果新记录包含其引用,我需要更新任何先前记录的值。
Table structure is as below : 表结构如下:
Review_Table
(review_id number pk,
review_name varchar2,
previous_review number null,
followup_review number null
)
Here previous_review and followup_review columns are objects of same table ie Review_table. 在这里,previous_review和followup_review列是同一表(即Review_table)的对象。
Now consider we have two records in Review_table A and B, A does not have any previous or followup review. 现在考虑我们在Review_table A和B中有两个记录,A没有任何先前或后续的审查。 When user creates/updates the record B and he selects record A as previous record, then we want to automatically update (via trigger) the value of A record's followup review with B's Review ID.
当用户创建/更新记录B并选择记录A作为先前的记录时,我们要使用B的评论ID自动(通过触发)更新A记录的后续评论的值。
I have tried writing following trigger 我尝试在触发器之后编写
create or replace trigger "REVIEW_T1"
AFTER insert or update on "REVIEW_TABLE"
for each row
begin
update REVIEW_TABLE
set review_follow_up_review = :new.REVIEW_ID
where REVIEW_ID = :new.REVIEW_PREVIOUS_REVIEW;
end;
But I am getting error as : REVIEW_TABLE is mutating, trigger/function may not see it ORA-06512 但是我收到错误消息,因为:REVIEW_TABLE正在变异,触发器/函数可能看不到它ORA-06512
I have tried searching everything but was unable to find any solution for it 我尝试搜索所有内容,但找不到任何解决方案
TL;DR: No trigger, no mutating. TL; DR:无触发器,无变异。 Do not use trigger to change another row in the same table.
不要使用触发器更改同一表中的另一行。
I absolutely agree with @StevenFeuerstein's comment : 我绝对同意@StevenFeuerstein的评论 :
I also suggest not using a trigger at all.
我还建议完全不使用触发器。 Instead, create a package that contains two procedures, one to insert into table, one to update.
而是,创建一个包含两个过程的程序包,一个过程要插入表中,一个过程要更新。 And within these procedures, implement the above logic.
在这些过程中,实现上述逻辑。 Then make sure that the only way developers and apps can modify the table is through this package (don't grant privs on the table, only execute on the package).
然后确保开发人员和应用程序可以修改表的唯一方法是通过此程序包(不要在表上授予privs,只能在程序包上执行)。
Take a look at the following example. 看下面的例子。
Prepare the schema: 准备架构:
create table reviews (
id number primary key,
name varchar2 (32),
previous number,
followup number
);
create or replace procedure createNextReview (name varchar2, lastId number := null) is
lastReview reviews%rowtype;
nextReview reviews%rowtype;
function getLastReview (lastId number) return reviews%rowtype is
begin
for ret in (
select * from reviews where id = lastId
for update
) loop return ret; end loop;
raise_application_error (-20000, 'last review does not exist');
end;
procedure insertReview (nextReview reviews%rowtype) is
begin
insert into reviews values nextReview;
exception when others then
raise_application_error (-20000, 'cannot insert next review');
end;
procedure setFollowUp (nextId number, lastId number) is
begin
update reviews set
followup = nextId
where id = lastId
;
exception when others then
raise_application_error (-20000, 'cannot update last review');
end;
begin
if lastId is not null then
lastReview := getLastReview (lastId);
end if;
nextReview.id := coalesce (lastReview.id, 0)+1;
nextReview.name := name;
nextReview.previous := lastId;
insertReview (nextReview);
if lastReview.Id is not null then
setFollowUp (nextReview.id, lastReview.Id);
end if;
exception when others then
dbms_output.put_line (
'createNextReview: '||sqlerrm||chr(10)||dbms_utility.format_error_backtrace ()
);
end;
/
Execute: 执行:
exec createNextReview ('first review')
exec createNextReview ('next review', 1)
See the outcome of work done: 查看已完成工作的结果:
select * from reviews;
ID NAME PREVIOUS FOLLOWUP
---------- ---------------- ---------- ----------
1 first review 2
2 next review 1
First you need to read about triggers, mutating table error and compound triggers: http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS2005 首先,您需要阅读有关触发器,表错误突变和复合触发器的信息: http : //docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS2005
Your trigger is AFTER UPDATE OR INSERT. 您的触发器是AFTER UPDATE或INSERT。 Means if you run UPDATE OR INSERT statements on this table, the trigger will fire.
意味着如果在此表上运行UPDATE或INSERT语句,触发器将触发。 But you are trying to update the same table again inside your trigger, which is compl.
但是您尝试在触发器内部再次更新同一表,即compl。 wrong.
错误。
I think you can fix this by rewriting this as a before trigger, rather than an after trigger. 我认为您可以通过将其重写为之前触发器而不是之后触发器来解决此问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.