错误的原因
该错误是在编写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;
分享到:
相关推荐
### 如何处理错误ORA-29275:部分多字节字符 #### 问题背景与描述 在Oracle数据库操作过程中,用户可能会遇到一个特定的错误提示——ORA-29275:部分多字节字符。这一错误通常出现在执行查询`SELECT * FROM V$...
oracle报错ora-12541:TNS无监听程序
在Oracle数据库系统中,"ORA-01036:非法的变量名/编号"是一个常见的错误,通常出现在PL/SQL代码或者SQL查询语句中,当你尝试使用一个不正确或者未定义的变量时,Oracle数据库会抛出这个错误。这个错误可能是由于...
然而,当你尝试向CLOB字段插入数据时,如果超过了Oracle规定的最大限制,就会遇到“ORA-01704: 文字字符串过长”的错误。这个错误通常意味着你试图插入的字符串超过了Oracle数据库允许的最大长度,对于VARCHAR2类型...
oracle12c程序连接时异常: ORA-01017: 用户名/口令无效; 登录被拒绝 的解决方案。
### Oracle 断电导致控制文件不一致报错 ORA-00214 处理方法 #### 问题概述 在Oracle数据库管理过程中,遇到控制文件版本不一致的问题时,通常会收到ORA-00214错误提示。此错误表示数据库中的一个或多个控制文件与...
Oracle数据库报错ORA-00904: 标识符无效问题解决办法,有可能是字段名或者表名写错了,也有可能是
### ora-01033: Oracle Initialization or Shutdown in Progress 解决方法 #### 一、问题背景及原因 **标题**: “ora-01033: Oracle initialization or shutdown in progress 解决方法” **描述**: “ora-01033: ...
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/...
在Oracle数据库管理中,"ORA-00990: 权限缺失或无效"是一个常见的错误代码,它表示用户尝试执行的操作没有足够的权限。这个错误通常发生在试图访问、修改或者管理数据库对象(如表、视图、索引等)时。在本篇文章中...
### Oracle 12c ORA-01017 错误详解及解决方案 #### 错误概述 在Oracle数据库管理过程中,用户可能会遇到ORA-01017错误:“用户名/口令无效;登录被拒绝”。这一错误通常出现在尝试连接数据库时,提示提供的用户名...
总之,"ORA-28040:没有匹配的验证协议"是一个常见的Oracle连接问题,需要结合Kettle的配置和Oracle数据库的设置来解决。通过以上分析和解决方案,你应该能够找到解决问题的方法,顺利连接到Oracle 12c数据库。
前言 最近在工作中遇到了一个问题,错误是...DBCA报错,首先看DBCA的日志,日志中也是报ORA-12547: TNS:lost contact 于是再sqlplus / as sysdba敲回车,也是报ORA-12547: TNS:lost contact, 基于之前的工程经验,先
### Oracle报错大全(珍藏版) #### ORA-00001: Unique Constraint Violated 当尝试插入或更新违反唯一约束的数据时触发此错误。例如,在具有唯一索引的列上插入重复数据。 #### ORA-00017: Rollback Segment Full...
在使用Oracle Data Pump工具IMPDP(Import Data Pump)进行数据导入的过程中,可能会遇到ORA-39002和ORA-39070等错误。本文将针对这些错误的排查方法进行详细介绍,帮助用户理解问题的原因及解决策略。 ### 错误...
ORA-00604: 递归SQL层1出现错误 ORA-03106: 致命的双工通信协议错误 ORA-02063: 紧接着line(源于dblink) 以及 ORA-04052: 在查找远程对象时出错 ORA-00604: 递归SQL层1出现错误 ORA-03120: 双工转换例行程序:整数...
ORA-12154: TNS: 无法解析指定的连接标识符的解决方法
ORA-00933: SQL command not properly ended ``` 解决方法是确保SQL语句完整无误,并使用正确的语法进行删除操作。 #### 四、总结 Oracle的回收站功能为用户提供了一个方便的方式来管理数据库对象的删除与恢复,极...
在Oracle数据库中,"ORA-00904"是一个常见的错误代码,它表示尝试引用一个不存在或无效的标识符。在这个场景下,错误信息提到的是"WM_CONCAT"函数,这表明在Oracle 19c数据库环境中,用户尝试使用WM_CONCAT函数,但...