GBase 8s SQL 指南:教程 / 对多用户环境编程 |
EXEC SQL DECLARE master CURSOR FOR EXEC SQL DECLARE detail CURSOR FOR FOR UPDATE EXEC SQL OPEN master; while(SQLCODE == 0) { EXEC SQL FETCH master INTO if(SQLCODE == 0) { EXEC SQL BEGIN WORK; EXEC SQL OPEN detail USING EXEC SQL FETCH detail EXEC SQL UPDATE WHERE CURRENT OF detail EXEC SQL COMMIT WORK; } } EXEC SQL CLOSE master;
在此设计中,使用一个游标来扫描表。选择了的记录用作更新不同的表的基础。问题在于,当将每一更新当做分开的事务处理时(如前一示例中伪代码所示),跟在 UPDATE 之后的 COMMIT WORK 语句关闭所有游标,包括主游标。
最简单的替代方案是将 COMMIT WORK 语句和 BEGIN WORK 语句分别移到最后一个语句和第一个语句, 这样,对整个主表的扫描就是一个大事务。将主表的扫描作为一个大事务来处理,有时是可能的,但如果需要更新许多行,它可变得不现实。锁的数目可能太大,并且在程序期间持有它们。
GBase 8s 数据库服务器支持的解决方案是将关键字 WITH HOLD 添加到主游标的声明。引用这样的游标作为持有游标,在不在事务结束时关闭。数据库服务器仍然关闭所有其他游标,且它仍然释放所有锁,但持有游标保持打开,直到显式地关闭它为止。
在您尝试使用持有游标之前,您必须确保了解此处描述的锁定机制,且您还必须了解正在并发地运行的程序。每当执行 COMMIT WORK 时,释放所有锁,包括放置在任何通过该持有游标访存的行上的任何锁。
对于对表的单向扫描,如果如您所愿地使用游标,则锁的移除无关紧要。然而,您可为任何游标指定 WITH HOLD,包括更新游标和滚动游标。在您这么做之前,您必须了解该事实的含义,即,在事务结束时,释放所有锁(包括对整个表的锁)。