请问大虾有关oracle中的触发器问题,小弟急用,先多谢各位大虾了(100分)

  • 主题发起人 主题发起人 wavey
  • 开始时间 开始时间
W

wavey

Unregistered / Unconfirmed
GUEST, unregistred user!
[:)]
本人在开发一个项目,用到oracle数据库,因为本人之前没有用个oracle。问题以下:
我在创建触发器时,发生这样的错误:
我数据库中有表:list,history两个表。我想在修改表list时更新表history,之后把list
中update过的记录删除。我创建触发器的语句是
create or replace trigger up_list
after update on list
for each row
begin
insert into history select PHONENO,INFOID,INFOLIFE,INFOPRI,CALLEDNO,INFOSTATE,CRYPT,INFOFALSE,INFODATE,CONTENT,PASSWD,NOTICE from list where infostate='1';
delete from list where infostate='1'
end
出现的错误是:
警告: 创建的触发器带有编译错误。
但在数据库中已经存在该触发器。
之后我手工改动list中的记录时
update list set infostate ='1' where infoid=1
出错提示为

ERROR 位于第 1 行:
ORA-04098: 触发器 'A.UPINFO_LIST' 无效且未通过重新确认


 
Oracle的Trigger不允许对定义在上面的表进行Insert、Update及Delete操作,以免引起
循环触发。你可以将需要删除的记录作上输出标记变通完成该项操作。
 
首先多谢GZZBY,但我还是不明白你说的“Oracle的Trigger不允许对定义在上面的表进行
Insert、Update及Delete操作”的“对定义在上面的表”是什么?
还有我是想把list表中的记录copy到history 中去,之后把list中相应的记录删除。
希望大虾说详细点好吗?
 
begin insert into history set PHONENO:=old.PHONENO........ ; if SQLCODE < 0 then
rollback;
return;
end if; delete where infoid=1;if SQLCODE < 0 then
rollback;
return;
end if; end;
 
因为你的触发器中是针对Update表List时触发的,但你的触发器中又有删除List表内容的动
作,那么又要触发你的触发器,这不是死循环吗?你先将下面
delete from list where infostate='1'
这一句去掉,看能不能通过.
我有一个以前写的触发器,你要不要看一下.
--BOM档触发器
create or replace TRIGGER UPDATE_BOM
AFTER INSERT OR UPDATE OR DELETE OF par_no
on BOM
FOR EACH ROW
begin
if (substr(:NEW.par_no,1,1)>='0') and (substr(:NEW.par_no,1,1)<='9') then
begin
if Inserting then
begin
Insert into partcut(sty_no,par_no,cus_no) values(:NEW.sty_no,:NEW.par_no,:NEW.cus_no);
end;
end if;
if updating then
begin
update partcut set sty_no=:NEW.sty_no,par_no=:NEW.par_no,cus_no=:NEW.cus_no where sty_no=:OLD.sty_no and par_no=:OLD.par_no and cus_no=:OLD.cus_no;
end;
end if;
if deleting then
begin
delete from partcut where sty_no=:OLD.sty_no and par_no=:OLD.par_no and cus_no=:OLD.cus_no;
end;
end if;
end;
end if;
end;

 
"定义在上面的表"意思是,如果写list表的Trigger,在该触发子中,不允许出现对该表
即list表的插入、修改及删除操作语句,否者会引起循环触发的问题。
你的触发子编译没有通过,所以不能调用。你不能通过lis的触发子删除list表中的记录,
只能通过在修改记录后,调用过程来删除list表中的记录,可以通过事务来保证数据的完整
性。
 
zhangkan
我已经是很简单的语句了。但编译时还是出这样的错。
create or replace TRIGGER UPDATE_BOM
AFTER INSERT OR UPDATE OR DELETE OF infostate
on info_list
FOR EACH ROW
begin
insert into info_history select PHONENO,INFOID,INFOLIFE,INFOPRI,CALLEDNO,INFOSTATE,CRYPT,INFOFALSE,INFODATE,CONTENT,PASSWD,NOTICE from info_list where infostate='1';
end;
警告: 创建的触发器带有编译错误。
你看上面的语句应该是对的吧?

 
建测试表
create table tt1 (no varchar2(20), name varchar2(10));
create table tt2 (no varchar2(20), name varchar2(10));
建触发器
create or replace trigger update_test
after insert or update or delete of no
on tt1
for each row
begin
insert into tt2 select no,name from tt1 where no='1';
end;
/
我在SQL中用此法成功的建立了一个Trigger,但在具体执行中还是有错.
ORA-04091: table SUPER.TT1 is mutating, trigger/function may not see it
ORA-06512: at "SUPER.UPDATE_TEST", line 2
ORA-04088: error during execution of trigger 'SUPER.UPDATE_TEST'
我想你通不过的原因是你的SQL有问题,你先要这一句放到SQL PLUS中试试看有没有问题.
因为表正在变动,所以这样子有错.我建议使用:OLD或:NEW参数才不会错.
因为你设的TRIGGER是针对每一列的,所以每一列变动都会被抓到,而且当前表正在修改还
没有COMMIT,所以你要参考表1就不能Select表1的资料,我改成下面的就成功,你参考一下.
create or replace trigger update_test
after insert or update or delete of no
on tt1
for each row
begin
insert into tt2 values(:NEW.no,:NEW.name);
end;

你的表改成下列看看能不能行:
create or replace TRIGGER UPDATE_BOM
AFTER INSERT OR UPDATE OR DELETE OF infostate
on info_list
FOR EACH ROW
begin
insert into info_history values(:NEW.PHONENO,:NEW.INFOID,:NEW.INFOLIFE,:NEW.INFOPRI,:NEW.CALLEDNO,:NEW.INFOSTATE,:NEW.CRYPT,:NEW.INFOFALSE,:NEW.INFODATE,:NEW.CONTENT,:NEW.PASSWD,:NEW.NOTICE);
end;
试了许久,不过这下子我也多了一点知识.
 
thank you zhangkan
编译的时候是没有错误了。
但我用手工调试的时候调用触发器的时候还是出错了。你能帮我看看吗?
但你那个列子我试了也行。
 
跟字段的类型有关系吗?
 
你出错的错误代码是否跟我上面贴出来的一样?照我下面的例子有问题吗?这个跟字段类型无
关,当然你两个表要交换的数据类型一定要一样,这是最基本的要求,甚至长度都最好一样,因
为在触发器中出了问题在程序中不好捕捉,也不好改.若你这儿还有什么问题,可以写信告诉我.
kan@freetrend.com.vn
题外话:你们在用COM+开发程序吗?
 
我还想问问在oracle中date类型在insert的时候是怎么表示的?
insert into test(testtime) values(sysdate);这样是可以的
但我
insert into test(testtime) values('20011023')就不行了。如果是数据应怎么样?
 
后退
顶部