我是学习Oracle的新手。我有一个任务,如果新记录包含其引用,我需要更新任何先前记录的值。
表结构如下:
Review_Table
(review_id number pk,
review_name varchar2,
previous_review number null,
followup_review number null
)
这里的previous_review和followup_review列是同一个表的对象,即Review_table。
现在考虑我们在Review_table A和B中有两条记录,A没有任何先前或后续审查。当用户创建/更新记录B并且他选择记录A作为前一记录时,我们希望使用B的评论ID自动更新(通过触发)A记录的后续评论的值。
我试过写下面的触发器
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;
但我收到错误:REVIEW_TABLE正在变异,触发/功能可能看不到它ORA-06512
我试过搜索一切,但无法找到任何解决方案
TL; DR:没有触发器,没有变异。不要使用触发器来更改同一个表中的另一行。
我绝对同意@StevenFeuerstein's comment:
我还建议不要使用触发器。相反,创建一个包含两个过程的包,一个用于插入表,另一个用于更新。在这些程序中,实现上述逻辑。然后确保开发人员和应用程序可以修改表的唯一方法是通过此包(不要在表上授予privs,只在包上执行)。
看一下下面的例子。
准备架构:
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;
/
执行:
exec createNextReview ('first review')
exec createNextReview ('next review', 1)
看看完成的工作成果:
select * from reviews;
ID NAME PREVIOUS FOLLOWUP
---------- ---------------- ---------- ----------
1 first review 2
2 next review 1
首先,您需要阅读有关触发器,变异表错误和复合触发器的信息:http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS2005
您的触发器是更新或插入后。表示如果在此表上运行UPDATE OR INSERT语句,则触发器将触发。但是你试图在你的触发器内再次更新同一个表,这是compl。错误。
我认为你可以通过将其重写为前触发器而不是后触发器来解决这个问题。