ORACLE 关于CURSOR中的FOR UPDATE关键字

有如下代码:

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 是最基本的需要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值