错误的原因
该错误是在编写trigger时常遇到的问题,其根本原因是由于对本表的操作造成的.ORACLE DB里默认在写TRIGGER的时候把本表锁死,不允许对其进行操作,当对某个表T进行update时,在trigger的body或trigger调用的存储过程又有对update表的查询,这时常会碰到该错误。
治标的解决办法
利用自治事物进行解决。
自治事物的概念:就是在subprogram里进行事物的提交不影响主程序的事务,同样主程序的提交或回滚都不影响子程序的commit,即子程序的事物和主程序的事物完全独立。
Exp1:
SQL> CREATE TABLE T(ID NUMBER(18),MC VARCHAR2(20),DT DATE);
表已创建。
SQL> CREATE OR REPLACE TRIGGER TR_T
2 AFTER DELETE ON T
3 FOR EACH ROW
4 DECLARE V_COUNT NUMBER;
5 --PRAGMA AUTONOMOUS_TRANSACTION;
6 BEGIN
7 INSERT INTO T VALUES(:OLD.ID,:OLD.MC,SYSDATE);
8 COMMIT;
9 END TR_DEL_CABLE;
10 /
触发器已创建
SQL> INSERT INTO T VALUES(1,'111111',SYSDATE);
已创建 1 行。
SQL> INSERT INTO T VALUES(2,'222222',SYSDATE);
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> SELECT ID,MC,TO_CHAR(DT,'YYYYMMDD HH24:MI:SS') FROM T;
ID MC TO_CHAR(DT,'YYYYM
---------- -------------------- -----------------
1 111111 20080802 11:07:36
2 222222 20080802 11:07:43
SQL> DELETE FROM T WHERE ID=1;
DELETE FROM T WHERE ID=1
*
第 1 行出现错误:
ORA-04091: 表 TEST.T 发生了变化, 触发器/函数不能读它
ORA-06512: 在 "TEST.TR_T", line 4
ORA-04088: 触发器 'TEST.TR_T' 执行过程中出错
SQL> SELECT ID,MC,TO_CHAR(DT,'YYYYMMDD HH24:MI:SS') FROM T;
ID MC TO_CHAR(DT,'YYYYM
---------- -------------------- -----------------
1 111111 20080802 11:07:36
2 222222 20080802 11:07:43
SQL> CREATE OR REPLACE TRIGGER TR_T
2 AFTER DELETE ON T
3 FOR EACH ROW
4 DECLARE V_COUNT NUMBER;
5 PRAGMA AUTONOMOUS_TRANSACTION;
6 BEGIN
7 INSERT INTO T VALUES(:OLD.ID,:OLD.MC,SYSDATE);
8 COMMIT;
9 END TR_DEL_CABLE;
10 /
触发器已创建
SQL> DELETE FROM T WHERE ID=1;
已删除 1 行。
SQL> COMMIT;
提交完成。
SQL> SELECT ID,MC,TO_CHAR(DT,'YYYYMMDD HH24:MI:SS') FROM T;
ID MC TO_CHAR(DT,'YYYYM
---------- -------------------- -----------------
2 222222 20080802 11:07:43
1 111111 20080802 11:08:32
(注:此前有人说可以通过把NEW OLD中的值放到local变量或package变量中可以避免此类错误,但我尝试过很多,还是照样抛出该错误,故将值存到变量中的方法不可行。)
治本的办法
首先自治事务必须慎用,因为一个DML可能会产生许多个独立的事物,这很容易引发死锁,ASKTOM上对AUTONOMOUS_TRANSACTION的看法是:唯一的用途就是作审计日志,其他一概不该使用。
治本的办法就是彻底废除trigger,把相应的处理逻辑放到存储过程中。
CREATE OR REPLACE PACKAGE BOM_AUTONUMBER
IS
TYPE t_MAX_SEQNUMBER is table of number INDEX BY PLS_INTEGER;
v_MAX_SEQNUMBER t_MAX_SEQNUMBER;
end BOM_AUTONUMBER
CREATE OR REPLACE TRIGGER TR_BOM_AUTONUMBER_SEQNUMBER
BEFORE INSERT
ON BOM
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
vNumber number;
vBOMID number;
BEGIN
vNumber:= 0;
vBOMID:= :New.BOMID;
if not BOM_AUTONUMBER.v_MAX_SEQNUMBER.EXISTS(vBOMID) then
SELECT GREATEST(nvl(Max(to_number(SEQ_NUMBER)),0), Count(*)) INTO vNumber FROM BOM Where ITEM = vBOMID;
BOM_AUTONUMBER.v_MAX_SEQNUMBER(vBOMID) := nvl(vNumber, 0);
end if;
BOM_AUTONUMBER.v_MAX_SEQNUMBER(vBOMID) := BOM_AUTONUMBER.v_MAX_SEQNUMBER(vBOMID) + 1;
:NEW.SEQ_NUMBER := BOM_AUTONUMBER.v_MAX_SEQNUMBER(vBOMID);
END TR_BOM_ AUTONUMBER_SEQNUMBER;
分享到:
相关推荐
CLOB字段类型报错 ORA-01704:文字字符串过长的解决
oracle报错ora-12541:TNS无监听程序
ORA-01036:非法的变量名/编号 oracle特有的错误
oracle12c程序连接时异常: ORA-01017: 用户名/口令无效; 登录被拒绝 的解决方案。
在运行查询SELECT * FROM V$SESSION 会出现ORA-29275:部分多字节字符的错误,这是什么原因开始我不得其解,网上也没有介绍什么好办法。本文给出答案。
ora-01033:oracle initialization or shutdown in progress 解决方法 ora-01033:oracle initialization or shutdown in progress 解决方法 ora-01033:oracle initialization or shutdown in progress 解决方法 ora-...
kettle连接oracle12C--报错ORA-28040 没有匹配的验证协议
ORA-32001:write to spfile requested but no spfile is in use请求写入spfile,但没有使用spfile的解决方法 在输入以下语句中报了这样的错误: SQL>alter system set control_files=’/u01/app/oracle/oradata/prod/...
ORA-12154: TNS: 无法解析指定的连接标识符的解决方法
主要介绍了解决django migrate报错ORA-02000: missing ALWAYS keyword,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
前言 最近在工作中遇到了一个问题,错误是...DBCA报错,首先看DBCA的日志,日志中也是报ORA-12547: TNS:lost contact 于是再sqlplus / as sysdba敲回车,也是报ORA-12547: TNS:lost contact, 基于之前的工程经验,先
ORA-00031:标记要终止的会话解决方案; ORA-00031:标记要终止的会话解决方案;
调整参数后引起,ORA-00838: Specified value of MEMORY_TARGET is too small, needs to be at least 3 2768M 的解决方案
Oracle数据库报错ORA-00904: 标识符无效问题解决办法,有可能是字段名或者表名写错了,也有可能是
错误描述:oracle远程连接服务器出现 ORA-12170 TNS:连接超时 错误检查:有很多是oracle自身安装的问题,但是我这里服务器配置正常,监听正常,服务正常,远程可以ping通服务器。 这里主要是防火墙问题,解决办法: ...
NULL 博文链接:https://3w1h.iteye.com/blog/1211779
oracle数据库优化之后,报错报错“ora-00838”的处理方法
oracle启动失败,ORA-00702报错,windows,linux系统下解决办法
NULL 博文链接:https://springlin.iteye.com/blog/1520668