Sql 触发器计数行给出ORA-04091:表正在变化,触发器/函数可能看不到它
更新表时出现此错误Sql 触发器计数行给出ORA-04091:表正在变化,触发器/函数可能看不到它,sql,oracle,plsql,sql-update,database-trigger,Sql,Oracle,Plsql,Sql Update,Database Trigger,更新表时出现此错误 UPDATE "Username"."EMPPROJECT" SET ENDDATE = TO_DATE('2016-09-11 00:00:00', 'YYYY-MM-DD HH24:MI:SS') WHERE ROWID = 'AAF+8XAAEAAGBIGAAB' AND ORA_ROWSCN = '537035617' 保存对表“用户名”的更改时出错。“EMPPROJECT”:第8行: ORA-04091:表Username.EMPPROJECT正在
UPDATE "Username"."EMPPROJECT"
SET ENDDATE = TO_DATE('2016-09-11 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
WHERE ROWID = 'AAF+8XAAEAAGBIGAAB'
AND ORA_ROWSCN = '537035617'
保存对表“用户名”的更改时出错。“EMPPROJECT”:第8行:ORA-04091:表Username.EMPPROJECT正在变异,触发器/函数可能 看不到ORA-06512:在“用户名.检查重叠日期更新”第4行
ORA-04088:执行触发器“Username.CHECKOVERLAPDATEUPDATE”时出错 触发器的定义如下:
create or replace trigger checkOverlapDateUpdate
before Update on EmpProject
for each row
declare
countOfOverlap integer;
begin
select count(*)
into countOfOverlap
from EmpProject EP
where isOverlapping(:new.startDate, :new.endDate, startDate, endDate) = 1
and EP.EmpID = :new.EmpId;
if countOfOverlap > 0
then
RAISE_APPLICATION_ERROR(-00000, 'Overlapping Insertion Dates');
rollback;
end if;
end;
Oracle试图告诉您的是:
针对每行)
update empproject set startdate = startdate + 100, enddate = enddate + 100;
这应该不是问题,因为所有日期范围的移位天数都相同。但是,当更新第一行并单独查看时,可能会发生冲突,因为其他行尚未更改。表中甚至可能只有两行,中间情况会导致日期范围重叠。然后,它将突然取决于Oracle首先选择两行中的哪一行进行更新。在一种情况下,更新将在没有错误的情况下运行,在另一种情况下,它将崩溃。一个不确定的结果,这当然是不允许的
解决方法是在完成更新后检查行
您可以为每一行编写一个更新后语句触发器(即在EmpProject上更新后而不使用),并将表中的每一行与所有其他行进行比较。在一张大桌子上,这可能相当昂贵
首选方法是写入复合触发器。此触发器将为更改的行(或其键)创建一个数组。在触发器的每行之后
部分,您将该行添加到数组中,在触发器的AFTER语句之后
部分,您将检查每一行的重叠范围
这里描述了计算触发器:Oracle试图告诉您的是:
更新可以跨越多行
但是,触发器会查看单行更新(针对每行)
由于多行update语句的单行更新以任意顺序发生,Oracle无法保证触发器中的子查询的结果是一致的、确定的
例如:
update empproject set startdate = startdate + 100, enddate = enddate + 100;
这应该不是问题,因为所有日期范围的移位天数都相同。但是,当更新第一行并单独查看时,可能会发生冲突,因为其他行尚未更改。表中甚至可能只有两行,中间情况会导致日期范围重叠。然后,它将突然取决于Oracle首先选择两行中的哪一行进行更新。在一种情况下,更新将在没有错误的情况下运行,在另一种情况下,它将崩溃。一个不确定的结果,这当然是不允许的
解决方法是在完成更新后检查行
您可以为每一行编写一个更新后语句触发器(即在EmpProject上更新后而不使用),并将表中的每一行与所有其他行进行比较。在一张大桌子上,这可能相当昂贵
首选方法是写入复合触发器。此触发器将为更改的行(或其键)创建一个数组。在触发器的每行之后
部分,您将该行添加到数组中,在触发器的AFTER语句之后
部分,您将检查每一行的重叠范围
这里描述了计算机触发器:您在谷歌上搜索过“正在变异,触发器/函数可能看不到它”吗?请浏览此链接。Jeffrey Kemp讨论了可用于实现“非重叠日期约束”的各种选项,to_DATE('2016-09-11 00:00:00','YYYY-MM-DD HH24:MI:SS')
可以写成日期'2016-09-11'
,“EMPPROJECT”
应该写成EMPPROJECT
。你在谷歌上搜索了吗“正在变异,触发器/函数可能看不到它”?浏览此链接。Jeffrey Kemp讨论了可以用来实现“非重叠日期约束”的各种选项,顺便说一句,到日期('2016-09-11 00:00:00','YYYY-MM-DD HH24:MI:SS')
可以写成日期'2016-09-11'
,以及“EMPPROJECT”
应写成empproject
。