oracle 中为什么在一个存储函数里不能同时进行查询和更新操作

shipatrioc 2002-04-12 09:06:32
我要写一个存储函数,该函数是这样实现的
我先声明一个cursor,然后open,
在循环fetch,每次fetch后我都要对该表的一个字段进行update
可我执行该函数时,出现下列错误.
SQL> select jiqing from dual;
select jiqing from dual
*
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "ORACLE.MARKS", line 4
ORA-06512: at "ORACLE.JIQING", line 21
ORA-06512: at line 1
其中,MARKS是更新字段的存储函数

我查了一下错误代码,如下
ORA-14551 cannot perform a DML operation inside a query

Cause: DML operation like insert, update, delete or select-for-update cannot be performed inside a query or under a PDML slave.

Action: Ensure that the offending DML operation is not performed or use an autonomous transaction to perform the DML operation within the query or PDML slave
我现在是不懂,难道再一个存储函数里不能,对一个表同时进行查询
和更新?望各位大虾指教
...全文
170 24 打赏 收藏 举报
写回复
24 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
wwl007 2002-04-12
cursor l is select * from bato for update of tmk;
那吗可以使用
open l;
fetch l into ....
while l%found loop
update bato set tmk='' where current of l;
end loop;
更新游标打开的那行
  • 打赏
  • 举报
回复
wwl007 2002-04-12
hrb_qiuyb(大森林)说得对!应该是那样的!
  • 打赏
  • 举报
回复
jlandzpa 2002-04-12
只是一个例子,证明是可以的.
  • 打赏
  • 举报
回复
pengz 2002-04-12
也?你的问题好象改变了,不是我说的了,,,

呵,奇怪,我理解力有问题
  • 打赏
  • 举报
回复
pengz 2002-04-12
不要在打开游标的情况下修改提交。
按照ANSII的标准SQL,这是不允许的。它将立刻关闭游标。
oracle进行了自己的扩展。
hrb_qiuyb(大森林) 的说法没错
“利用cursor更新表的操作是应该加*for update* 选项的。”

其他详细信息请看:
http://www.csdn.net/develop/read_article.asp?id=13192
  • 打赏
  • 举报
回复
shipatrioc 2002-04-12
re KingSunSha(弱水三千):
这只是我函数的一部分,还有其它好多操作,我省略了.
我现在想知道,再一个存储函数里能不能对一个表同时进行查询和更新
  • 打赏
  • 举报
回复
shipatrioc 2002-04-12
好像也不行,另外,我的update和select没有直接的关系,
update的条件是select的结果,我还试了下面的代码
create or replace function test
return number is
Money sgj.money%type;
begin
update sgj set money=1000;
commit;
Select money into Money from sgj;
return Money;
end;
/
出现的错误是一样的
  • 打赏
  • 举报
回复
KingSunSha 2002-04-12
这段代码有必要吗?完全可以用一句sql解决
  • 打赏
  • 举报
回复
jlandzpa 2002-04-12
10:57:08 SQL> select * from jlandzpa;

A B
---------- ----------
1 0

exec p_jlandzpa;
select * from jlandzpa;
10:57:52 SQL> select * from jlandzpa;

A B
---------- ----------
1 1
  • 打赏
  • 举报
回复
jlandzpa 2002-04-12
ok:
drop table jlandzpa;
create table jlandzpa(a varchar2(10),b varchar(10));
insert into jlandzpa values('1','0');
commit;
create or replace procedure p_jlandzpa as
cursor c1 is
select a,rowid from jlandzpa;
s_a varchar2(20);
s_rowid varchar2(20);
begin
open c1;
fetch c1 into s_a,s_rowid;
loop
update jlandzpa set b = '1'
where rowid = chartorowid(s_rowid);
commit;
fetch c1 into s_a,s_rowid;
exit when c1%notfound;
end loop;
close c1;
end;
/
exec p_jlandzpa;
select * from jlandzpa;
  • 打赏
  • 举报
回复
hrb_qiuyb 2002-04-12
忘加commit;了,自已加上吧
  • 打赏
  • 举报
回复
hrb_qiuyb 2002-04-12
利用cursor更新表的操作是应该加*for update* 选项的。

declare
cursor c1 is select col1,col1.. from table_name for update;
l_c1 c1%rowtype;
begin
open c1;
loop
fetch c1 into l_c1;
exit when c1%notfound;
update table_name set ...
where current of c1;
end loop
close c1;
end;


  • 打赏
  • 举报
回复
shipatrioc 2002-04-12
不行,我试了,有没有其他办法!
另外,我试了,先update在open cursor的情况,先update 在select into的情况
最后出的是一样的结果,难道....?
  • 打赏
  • 举报
回复
shipatrioc 2002-04-12
我试一下
  • 打赏
  • 举报
回复
jlandzpa 2002-04-12
try this:
cursor中把rowid取出来,update时用rowid更新.
  • 打赏
  • 举报
回复
shipatrioc 2002-04-12
create or replace function jiqing
return integer is
bsn bato.bsn%TYPE;
mid bato.mid%TYPE;
csn bato.csn%TYPE;
sac bato.sac%TYPE;
sco bato.sco%TYPE;
ety bato.ety%TYPE;
eat bato.eat%TYPE;
bpr bato.bpr%TYPE;
bqu bato.bqu%TYPE;

cursor fcursor is select bsn,mid,csn,sac,sco,eat,bpr,bqu from bato where tmk='D';
begin
open fcursor;
loop
fetch fcursor into bsn,mid,csn,sac,sco,eat,bpr,bqu;
update bato set tmk='T' where bsn=bsn and mid=mid;
commit;
exit when fcursor%notfound;
end loop;
close fcursor;
return 0;
end jiqing;
就是这样了
  • 打赏
  • 举报
回复
shipatrioc 2002-04-12
我试了commit也不行,代码太长,我整理一下,在贴出来
  • 打赏
  • 举报
回复
wwl007 2002-04-12
可以是可以的!一定要马上提交阿!commit,不然就会差先问题!
你还是把代码贴出了吧!让大家看看!也可以加上no wait
  • 打赏
  • 举报
回复
snowy_howe 2002-04-12
1、到Oracle论坛去提问。
2、详细列出你的存储过程。
3、我不能解决你的问题,:p
  • 打赏
  • 举报
回复
shipatrioc 2002-04-12
谢谢各位,其实各位的方法都可能是对的.是我的程序有问题.
exit when的位置方的不对.一上午的时光没白费,我又学到了
好多新东西,谢谢各位!
  • 打赏
  • 举报
回复
加载更多回复(4)
相关推荐
发帖
Sybase

2590

社区成员

Sybase相关技术讨论区
社区管理员
  • Sybase社区
加入社区
帖子事件
创建了帖子
2002-04-12 09:06
社区公告
暂无公告