游标中rollback引起游标关闭 _MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2779 | 回复: 0   主题: 游标中rollback引起游标关闭         下一篇 
    本主题由 Administrator 于 2014-9-16 15:19:53 移动
white
注册用户
等级:少校
经验:1327
发帖:305
精华:0
注册:2011-7-21
状态:离线
发送短消息息给white 加好友    发送短消息息给white 发消息
发表于: IP:您无权察看 2014-9-16 10:34:38 | [全部帖] [楼主帖] 楼主

序段:

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;


该贴由system转至本版2014-9-16 15:19:53



赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论