oracle中触发器问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle中触发器问题相关的知识,希望对你有一定的参考价值。

有二个表student,和score 关系模式是student(sno,sname,savg) score(sno,cno,score)
要求编写一个触发器 要求:
当更新学生成绩表SCORE中的学生成绩时,自动计算该学生的平均成绩保存到学生表SAVG字段中。
我个人在编写的构成中总是发生04091错误,请大家帮我写写啊,如何才可以解决这个变化表问题,请给出代码
create or replace trigger stu_upd
after update on score
referencing old as old new as new for each row
declare
t_savg number(6,2);
begin
select avg(score) into t_savg from score where sno=:new.sno;
update student set savg=t_savg where sno=:new.sno;
end;
这是我的错误的代码

参考技术A 在某个table的trigger里面,是不能select自己的.
所以,在score这个table的trigger里面,不能查询score的数据.

可能我说的是屁话,没有解决你的问题.但是原因就是这样的.
所以,只能是在trigger外面来做查询动作.
即写完update语句后,再查询,然后更新student
参考技术B 可以这样试试看

Create Or Replace Trigger Stu_Upd
Before Update On Score
Referencing Old As Old New As New
For Each Row
Declare
t_Savg Number(6, 2);
Function Get_Avg_Scode Return Number Is
x_Result Number;
Pragma Autonomous_Transaction;
Begin
Select Avg(Score) Into x_Result From Score Where Sno = :New.Sno;
Return x_Result;
Exception
When Others Then
Return - 99;
End;
Begin
t_Savg := Get_Avg_Scode;
Update Student Set Savg = t_Savg Where Sno = :New.Sno;
Exception
When Others Then
Raise_Application_Error('-20001', Sqlerrm);
End;本回答被提问者采纳
参考技术C 这样应该就可以了,不过自治事务用在业务比较复杂的数据库里面是要慎用的,很容易引发死锁,
create or replace trigger stu_upd
after update on score
referencing old as old new as new for each row
declare
pragma autonomous_transaction ;
t_savg number(6,2);
begin
select avg(score) into t_savg from score where sno=:new.sno;
update student set savg=t_savg where sno=:new.sno;
commit ;
end;
参考技术D 这种, Oracle 的触发器,要访问自己这个表的情况下。
我印象中,好像是要 外面另外建立一个 package,然那个 package 去检索当前表。
然后这个触发器,通过某种方式,去调用那个 package。

如何在 Oracle 中定义一个触发器 ON COMMIT?

【中文标题】如何在 Oracle 中定义一个触发器 ON COMMIT?【英文标题】:How to define a trigger ON COMMIT in Oracle? 【发布时间】:2011-05-05 04:02:20 【问题描述】:

oracle 数据库中是否有任何方法可以定义触发器,该触发器将在 COMMIT 之前同步触发(如果它抛出异常则 ROLLBACK)以防指定表被更改?

【问题讨论】:

【参考方案1】:

Oracle 中没有 ON COMMIT 触发机制。但是有一些解决方法:

    您可以使用带有 ON COMMIT REFRESH 的实体化视图并将触发器添加到此 MV。这将允许您在提交时修改基表时触发逻辑。如果触发器引发错误,事务将被回滚(您将丢失所有未提交的更改)。

    您可以使用 DBMS_JOB 将操作推迟到提交之后。这将是一个异步操作,在某些情况下可能是可取的(例如,当您希望在事务成功后发送电子邮件时)。如果您回滚主事务,则作业将被取消。作业和主会话是独立的:如果作业失败,则不会回滚主事务。

在您的情况下,您可能会使用选项 (1)。我个人不喜欢在触发器中编写业务逻辑,因为它会增加很多复杂性,但从技术上讲,我认为这是可行的。

【讨论】:

谢谢。选项 #1 对我来说很方便。 当然是一个很好的解决方案。只需考虑一下,ON COMMIT REFRESH 是当前事务的一部分,并且会延迟提交,直到刷新完成为止。如果 FAST REFRESH 复杂且不够快,它可能会减慢整个应用程序并导致更多的阻塞和锁定。如果 FAST REFRESH 不可行,那么可以考虑通过常规作业进行异步刷新。【参考方案2】:

我遇到了类似的问题,但不幸的是,选项 1 不适合我的情况。

“Ask Tom”也建议的另一种可能的解决方案是指定一个存储过程并在执行 COMMIT 之前简单地调用该过程。 此解决方案仅在您有权访问执行 COMMIT 的代码时才方便,但对我而言,这是最简单的解决方案。

【讨论】:

以上是关于oracle中触发器问题的主要内容,如果未能解决你的问题,请参考以下文章

获取触发 Oracle 触发器的值

oracle触发器中定时执行sql

oracle触发器查询中的问题

如何在 Oracle 中定义一个触发器 ON COMMIT?

Oracle 触发器调试及遇到相关问题解决

oracle 触发器 问题