首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Oracle 11中由函数引起的变异表

Oracle 11中由函数引起的变异表
EN

Stack Overflow用户
提问于 2012-03-29 23:49:55
回答 2查看 4.8K关注 0票数 13

我们最近已经从Oracle 10升级到Oracle 11.2。升级之后,我开始看到一个由函数而不是触发器引起的变异表错误(我以前从未见过这种错误)。这是在以前版本的Oracle中工作的旧代码。

下面是一个会导致错误的场景:

代码语言:javascript
复制
create table mutate (
    x NUMBER,
    y NUMBER
);

insert into mutate (x, y)
values (1,2);

insert into mutate (x, y)
values (3,4);

我创造了两行。现在,通过调用以下语句,我将加倍我的行:

代码语言:javascript
复制
insert into mutate (x, y)
select x + 1, y + 1 
from mutate;

这对于复制错误并不是绝对必要的,但它有助于后面的演示。表的内容现在如下所示:

代码语言:javascript
复制
X,Y
1,2
3,4
2,3
4,5

平安无事。现在是有趣的部分:

代码语言:javascript
复制
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语句结合起来:

代码语言:javascript
复制
insert into mutate (x, y)
select x + 2, y + 2
from mutate
where mutate_count() = 4;

结果是什么呢?此错误:

代码语言:javascript
复制
ORA-04091: table MUTATE is mutating, trigger/function may not see it
ORA-06512: at "MUTATE_COUNT", line 6

所以我知道是什么导致了这个错误,但是我很好奇为什么。Oracle不是在执行SELECT,检索结果集,然后执行这些结果的大容量插入吗?只有在查询完成之前已经插入了记录时,我才会期望发生变异的表错误。但如果甲骨文这么做了,之前的声明不是吗?

代码语言:javascript
复制
insert into mutate (x, y)
select x + 1, y + 1 
from mutate;

开始无限循环?

更新:

通过杰弗里的链接,我在甲骨文文档中找到了这个

默认情况下,Oracle保证语句级的读取一致性。单个查询返回的数据集相对于单个时间点是一致的。

他的职位中也有作者的评论

对于SQL语句中出现的重复函数调用,人们可能会争论为什么Oracle不确保这种“语句级读取一致性”。据我所知,这可能被认为是一种错误。但这是目前的工作方式。

我是否正确地假设这种行为在Oracle版本10和11之间发生了变化?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-30 01:45:40

首先,

代码语言:javascript
复制
insert into mutate (x, y)
select x + 1, y + 1 
from mutate;

不会启动无限循环,因为查询将看不到在语句开始时仅存在的数据。新行只对后续语句可见。

很好地解释了这一点:

当Oracle走出当前正在执行update语句的SQL-engine并调用该函数时,该函数--就像行后更新触发器一样--看到EMP的中间状态在update语句执行过程中是否存在。这意味着函数调用的返回值在很大程度上取决于行被更新的顺序。

票数 10
EN

Stack Overflow用户

发布于 2012-03-30 11:11:35

语句-级别读取一致性和事务级读取一致性“.

从手册中:

“如果选择列表包含一个函数,则数据库在语句级别应用语句级的读取一致性,用于在PL/SQL函数代码中运行,而不是在父SQL级别中运行。例如,函数可以访问另一个用户更改和提交数据的表。在函数中每次执行SELECT时,都会建立一个新的读取一致快照”。

这两个概念在“Oracle数据库概念”中都有解释:

01/server.102/b 14220/稠密.#sthref1955 1955

->>> 更新

->>>*Section 之后添加了OP被关闭的

规则

该技术规则由kemp先生(@jeffrey-kemp)很好地链接,Toon http://harmfultriggers.blogspot.com.au/2011/12/look-mom-mutating-table-error-without.html解释得很好,在"Pl/Sql语言引用-控制PL/SQL子程序的副作用“(您的函数违反RNDS读取不读取数据库状态)中报告了该规则:

从INSERT、UPDATE或DELETE语句调用时,该函数不能查询或修改该语句修改的任何数据库表。 如果一个函数查询或修改一个表,而该表上的DML语句调用该函数,则会发生ORA-04091 (变异表错误)。

http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/subprograms.htm#CHDJJCEC

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9935239

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档