楼主: berbang

[精华] 关于cursor中的for update关键字

[复制链接]
论坛徽章:
2
ERP板块每日发贴之星
日期:2006-04-22 01:01:36授权会员
日期:2006-04-22 05:54:17
41#
发表于 2006-4-30 20:27 | 只看该作者
好帖,长见识

使用道具 举报

回复
论坛徽章:
1
授权会员
日期:2006-05-08 09:05:38
42#
发表于 2006-5-1 09:07 | 只看该作者
存储过程结束用commit?

如果有这种情况,在Delphi写的程序中,启一个事务,事务中调用三个存储过程,
proc1
proc2
proc3

如果proc1成功,已commit
如果proc2不成功, 已rollback
那不是造成不一致的情况了吗?


最初由 app_kwan 发布
[B]

1>。在FOR UPDATE OF[/COLOR]之后所枚举的字段(column),不一定是要被更新的字段。 -- 这个Hendytai 己证明了。

2>。此外,要么不用NOWAIT[/COLOR];若用NOWAIT[/COLOR],就必需最少枚举一个任意字段(column)。否则PLS-00404出现。例子,

请教:关于FOR UPDATE OF .. NOWAIT

注:这限制在Version 9i 应会除去。

3>。但是,有些朋友总觉得在FOR UPDATE OF[/COLOR]之后所枚举的字段(column)是多余的,
所以还觉不爽 -- 通常有这感觉的,大多是爱完美,那也是好的。

而解决的方法就是直接用ROWID替代WHERE CURRENT OF [I]YOUR_CURSOR_NAME[/I][/COLOR]语句。
例子如下,

[php]
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;
[/php]


由此,我自己的FOR UPDATE习惯是,
  • NOWAIT[/COLOR]定然跟FOR UPDATE之后。
  • 直接用ROWID替代WHERE CURRENT OF [I]YOUR_CURSOR_NAME[/I][/COLOR]语句,
    尤其在相对繁习的程序里头。
  • COMMIT必需存在程序结尾。以防死锁成形。
  • EXCEPTION里的ROLLBACK是最基本的需要。


希望这对大家基本认识FOR UPDATE有帮助。







- app [/B]

使用道具 举报

回复
论坛徽章:
15
ITPUB元老
日期:2011-12-19 12:17:46山治
日期:2024-04-20 16:48:40罗罗诺亚·索隆
日期:2019-09-03 20:34:09托尼托尼·乔巴
日期:2019-02-01 10:41:05乌索普
日期:2017-11-22 09:58:19娜美
日期:2017-03-10 17:49:05妮可·罗宾
日期:2017-01-10 08:24:43金牛座
日期:2016-03-03 18:30:16秀才
日期:2015-11-30 09:59:2319周年集字徽章-19
日期:2025-09-14 15:00:16
43#
发表于 2006-5-1 18:54 | 只看该作者
好贴

使用道具 举报

回复
论坛徽章:
9
ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44生肖徽章2007版:鸡
日期:2008-01-02 17:35:53生肖徽章2007版:鼠
日期:2008-01-02 17:35:53生肖徽章2007版:猪
日期:2009-03-10 21:17:25生肖徽章2007版:猴
日期:2009-03-10 21:23:27生肖徽章2007版:牛
日期:2009-03-10 21:26:49生肖徽章2007版:鸡
日期:2009-03-10 21:36:09ITPUB8周年纪念徽章
日期:2009-09-27 10:21:22祖国60周年纪念徽章
日期:2009-10-09 08:28:00
44#
发表于 2006-7-12 00:30 | 只看该作者
后面不必加字段,只是为了说明用而已

使用道具 举报

回复
论坛徽章:
0
45#
发表于 2006-7-12 10:42 | 只看该作者
for update 引發的討論。值得一看。

使用道具 举报

回复
论坛徽章:
4
ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:442010新春纪念徽章
日期:2010-03-01 11:19:502011新春纪念徽章
日期:2011-02-18 11:43:362012新春纪念徽章
日期:2012-01-04 11:53:29
46#
发表于 2007-6-29 18:27 | 只看该作者
学习了。。。呵呵

使用道具 举报

回复
论坛徽章:
24
生肖徽章:狗
日期:2006-09-07 10:14:43数据库板块每日发贴之星
日期:2008-07-26 01:02:20生肖徽章2007版:兔
日期:2008-10-13 11:10:11奥运会纪念徽章:铁人三项
日期:2008-10-24 13:27:21开发板块每日发贴之星
日期:2008-12-27 01:01:09生肖徽章2007版:马
日期:2009-11-18 10:45:032010新春纪念徽章
日期:2010-03-01 11:21:02ITPUB9周年纪念徽章
日期:2010-10-08 09:28:51ERP板块每日发贴之星
日期:2011-05-18 01:01:01ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15
47#
发表于 2007-6-29 20:02 | 只看该作者
最初由 app_kwan 发布
[B]Berbang 兄台,

希望这对你有帮助



“FOR UPDATE OF” 是“行锁”(locks on the row) -- 不存在字段加锁!



这“行锁”的作用

1>。始于一个CURSOR 的OPEN时候,

2>。终于一个完整的传送 --  COMMITROLLBACK,而不是CURSOR 的完结
(CLOSE [I]your_cursor_name[/I]) 。

3>。若有两个CURSOR 对同一“行”(row)中任意字段(column)作出更改(UPDATE[/COLOR]),
时间上的后一CURSOR会一直等待,至第一个传送完结为止 -- COMMITROLLBACK

4>。若3>不被有效处理,死锁就成形。
例如:执行以下程序于两个session上,第二个session会一直处于等待。。。直至
第一个session执行COMMITROLLBACK为止。
[php]
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;
[/php]

5>。防止4>的方法之一是加NOWAITFOR UPDATE之后。如此,第二个session不会一
直等下去,而是出现ORA-00054 [resource busy and acquire with NOWAIT specified]
讯息。






- app [/B]

学习了!

使用道具 举报

回复
论坛徽章:
0
48#
发表于 2007-9-10 09:06 | 只看该作者
学习。。。

使用道具 举报

回复
论坛徽章:
0
49#
发表于 2007-9-10 10:05 | 只看该作者
向各位高手学习了
THANKS!

使用道具 举报

回复
论坛徽章:
0
50#
发表于 2007-12-23 15:32 | 只看该作者
原帖由 nothing315 于 2006-5-1 09:07 发表
存储过程结束用commit?

如果有这种情况,在Delphi写的程序中,启一个事务,事务中调用三个存储过程,
proc1
proc2
proc3

如果proc1成功,已commit
如果proc2不成功, 已rollback
那不是造成不一致的情况了吗?





可以采用自主事务处理的办法,自主事务处理可以暂停主事务并处理过程内的COMMIT或ROLLBACK操作,然后恢复主事务处理。

上面的语句如果存储过程proc2不采用自主事务处理,则其内部的ROLLBACK操作会影响到外层主事务

可以这样解决:
create or replace procedure proc2
as
PRAGMA AUTONOMOUS_TRANSACTION;
begin
语句主体;
end;

PRAGMA AUTONOMOUS_TRANSACTION;这一语句设定proc2为自主事务处理,其中的rollback或者commit操作都不会影响外层的事务。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表