Prayer

在一般中寻求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

游标中rollback引起游标关闭

Posted on 2010-06-10 10:39 Prayer 阅读(1501) 评论(0)  编辑 收藏 引用 所属分类: DB2
序段:
declare test_cur cursor with hold for
     select .... from A where ... order by ... with ur;

open test_cur;
while( 1 ){
    fecth test_cur into ......;
    判断SQLCODE

    begin_work();           /* 其实就是设置了一个标志 */
    SQL 操作,修改其他表或者游标所在表的数据
   根据结果判断 commit or rollback。    /* 此处如果rollback 游标被关闭 */
}

异常状态:
如果游标中进行了SQL操作,根据结果判断并rollback时,
下一次fetch时,会提示 501 没有打开游标。从而报错退出。
------------------------------
疑问:
使用前参考的文章:http://searchdatabase.techtarget.com.cn/tips/365/2297365.shtml
之中有说到: 
10.DB2的游标打开后遇到commit和rollback默认是会关闭的。保持游标打开的方法是在定义游标时加上with hold选项
但是,我declare 游标时使用了with hold选项,为什么还会出现这个问题?



额卖糕的

从vlife以前的回复中找到的答案:
无论是否使用with hold与否,rollback将释放session中的游标。commit只释放不带with hold的游标。
--------------------------------
救命啊。这些程序是从informix移植过来的。
难道让我将满足条件的记录全部读到一个结构数组里面,然后再从结构数组里面逐条取出处理么?
量很大的哈。。。。我死了。。。


摘自《SQL Reference Volume 2》
declare Cursor WITH HOLD
   Maintains resources across multiple units of work.

(1)For units of work ending with COMMIT:
   - Open cursors defined WITH HOLD remain open.
   - All locks are released, except locks protecting the current cursor position of open WITH HOLD cursors.
   。。。

(2)For units of work ending with ROLLBACK:
   -All open cursors are closed.
   -All locks acquired during the unit of work

这种方案是否可行

游标改用普通游标。
游标取出当前记录后,fork子进程。
主进程只管从游标取数。
子进程进行事务、处理、判断、修改状态、提交等等。
主进程等子进程的结束信号,然后取下一条记录。
程序段:
declare test_cur cursor with hold for
     select .... from A where ... order by ... with ur;

open test_cur;
while( 1 ){
    fecth test_cur into ......;
    判断SQLCODE

    pid = fork();

    if( pid == 0 ) {    /* 子进程干活 */
            sqledtin( &sqlca );
            setsid();
            signal( SIGHUP, SIG_IGN );

            db_disconn( G_mdb_name );
            begin_work();           /* 其实就是设置了一个标志 */
            SQL 操作,修改其他表或者游标所在表的数据。
        根据结果判断 commit or rollback。   
        db_disconn();
            exit();
    }

    /* 主进程等待子进程结束 */
}
close test_cur;


如果是两个不同的事务的话,你用CLI来写比较方便

用savepoint

在cursor内部设立一个savepoint, rollback时用
rollback to savepoint a;

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理