现在的位置: 首页 > 综合 > 正文

ORACLE 关于CURSOR中的FOR UPDATE关键字

2013年08月24日 ⁄ 综合 ⁄ 共 1703字 ⁄ 字号 评论关闭

有如下代码:

declare

    --
query emp
.
name

    cursor cur_emp

        is

    select empno
,
ename
,
job

      from emp

     where empno
=
7369

      
for
update of ename
;


begin

   
for
return_cur in cur_emp

    loop   

       update emp

          set ename
=
'LHG'

       
where current of cur_emp
;

   
end loop
;


end
;

其中的for update of ename

意思是给表中的行加锁,经过测试,后面的ename可以写成该表中的任何字段,因为oracle中锁的最低级别是行锁,不存在给字段加锁。

下面是行锁的作用:

1.行锁开始于一个CURSOR的OPEN,结束于一个提交COMMIT或ROLLBACK,而并不是结束于一个CURSOR的结束(CLOSE)。

2.当在一个CURSOR中对某个表的行加锁,那么如果在这个SESSION中用另一个CURSOR操作该行记录时候会等待第一个cursor的完成提交,直到第一个cursor提交完成之后,第二个cursor中对改行的操作才会开始执行。

3.当第一个cursor中的由于操作错误而不能提交时候,第二个cursor将会一直等待下去,这样就形成了死锁。预防这种情况发生的方法是在for update of ename 之后指定NOWAIT选项,这样的话,当第二个cursor不会一直等待下去,而是出现
ORA-00054 [resource busy and acquire with NOWAIT specified]



讯息。

4.既然for update of后面的字段是随便那个字段都可以,那么可不可以不写呢?如果你没必要指定NOWAIT选项,那么后面的字段就可以不写;如果你必须指定NOWAIT选项,则必须指定至少一个字段。

5.还有一种方法是用ROWID
替代WHERE CURRENT OF YOUR_CURSOR_NAME

语句。

如下代码:

declare

     --
query emp
.
name

     cursor cur_emp

         is

     select a
.
deptno
,

           
a
.
dname
,

           
a
.
rowid
,

           
b
.
rowid rowid_1

       from dept a
,
emp b

      where empno
=
7369

       
and
a
.
deptno
=
b
.
deptno

       
for
update nowait
;

     --
local variables

     v_deptno dept
.
deptno
%
type
;

    
v_dname dept
.
dname
%
type
;

    
v_rowid rowid
;

    
v_rowid_1 rowid
;


begin

     open cur_emp
;

    
loop

     fetch cur_emp into v_deptno
,
v_dname
,
v_rowid
,
v_rowid_1
;

     exit
when cur_emp
%
notfound
;

       
update dept

           set dname
=
'abc'

        
where rowid
=
v_rowid
;

       
update emp

           set ename
=
'frank'

        
where rowid
=
v_rowid_1
;

    
end loop
;

    
close cur_emp
;

    
commit
;


exception

     when others then

        rollback
;

       
raise
;


end
;

由此,推荐的for update的习惯是:

  • NOWAIT
    定然跟FOR UPDATE
    之后。
  • 直接用ROWID
    替代WHERE CURRENT OF YOUR_CURSOR_NAME

    语句,
    尤其在相对繁习的程序里头。
  • COMMIT
    必需存在程序结尾。以防死锁成形。
  • EXCEPTION
    里的ROLLBACK
    是最基本的需要。
  • 抱歉!评论已关闭.