【发布时间】:2012-04-13 16:22:07
【问题描述】:
我们最近从 Oracle 10 升级到了 Oracle 11.2。升级后,我开始看到由函数而不是触发器引起的变异表错误(我以前从未遇到过)。这是在早期版本的 Oracle 中工作的旧代码。
这是一个会导致错误的场景:
create table mutate (
x NUMBER,
y NUMBER
);
insert into mutate (x, y)
values (1,2);
insert into mutate (x, y)
values (3,4);
我创建了两行。现在,我将通过调用以下语句将行数加倍:
insert into mutate (x, y)
select x + 1, y + 1
from mutate;
这不是复制错误所必需的,但它有助于我稍后的演示。所以表格的内容现在看起来像这样:
X,Y
1,2
3,4
2,3
4,5
一切都好。现在是有趣的部分:
create or replace function mutate_count
return PLS_INTEGER
is
v_dummy PLS_INTEGER;
begin
select count(*)
into v_dummy
from mutate;
return v_dummy;
end mutate_count;
/
我创建了一个函数来查询我的表并返回一个计数。现在,我将它与 INSERT 语句结合起来:
insert into mutate (x, y)
select x + 2, y + 2
from mutate
where mutate_count() = 4;
结果?这个错误:
ORA-04091: table MUTATE is mutating, trigger/function may not see it
ORA-06512: at "MUTATE_COUNT", line 6
所以我知道是什么导致了错误,但我很好奇为什么。 Oracle 不是在执行 SELECT,检索结果集,然后 然后 执行这些结果的批量插入吗?如果在查询完成之前已经插入了记录,我只会期望发生变异表错误。但如果 Oracle 这样做了,那么之前的声明不会:
insert into mutate (x, y)
select x + 1, y + 1
from mutate;
开始无限循环?
更新:
通过 Jeffrey 的链接,我在 the Oracle docs 找到了这个:
默认情况下,Oracle 保证语句级读取一致性。这 单个查询返回的数据集与 单个时间点。
his post还有作者的评论:
有人可能会争论为什么 Oracle 不确保这种“语句级读取” 一致性'用于出现在 SQL 中的重复函数调用 陈述。就我而言,它可以被认为是一个错误。但 这是它目前的工作方式。
我是否正确假设此行为在 Oracle 版本 10 和 11 之间发生了变化?
【问题讨论】:
标签: sql oracle plsql oracle10g oracle11g