2011-11-03 28 views
2

是否有一种更简单的方法来关闭PL/SQL程序(Oracle 10G)中的所有打开的游标。从pl/sql异常块中关闭所有游标'一次'

我有一个程序可以产生一些例外。要正常退出,我需要检查是否有 任何游标打开和关闭它们。这是我结束的那种情况。

Procedure test 
is 
-- 
--- 
Begin 
-- 
-- 
Exception 
when no_data_found then 
    if cursorA%isopen close 
    if cursorB%isopen close 
    if cursorC%isopen close 
when invalid_date then 
    if cursorA%isopen close 
    if cursorB%isopen close 
    if cursorC%isopen close 
when invalid_user then 
    if cursorA%isopen close 
    if cursorB%isopen close 
    if cursorC%isopen close 
when others then 
    if cursorA%isopen close 
    if cursorB%isopen close 
    if cursorC%isopen close 

End test; 

很明显,以上并不理想,特别是如果有很多异常条款。与其对每个异常块执行相同的检查,是否有更快的方法来关闭所有打开的光标?注意:它只需要关闭由当前运行的pl/sql程序打开的游标,因为可能还有其他可能会打开游标的pl/sql程序。

在此先感谢

+0

不太熟悉Oracle异常语法,但是您能否将所有的游标关闭语句放在一边测试您正在处理的异常类型? – n8wrl

+0

否,因为发生异常时,控制权跳转到相关异常块的第一行。在某些情况下,我无法控制何时会引发异常。 – ziggy

回答

11

你确定你需要使用显式游标语法摆在首位,而不是使用隐式游标?如果使用隐式游标,Oracle会自动打开和关闭它们。你可以声明查询在线或脱节作为块下面

DECLARE 
    CURSOR cursor_a 
     IS SELECT * 
      FROM emp; 
BEGIN 
    FOR a IN cursor_a 
    LOOP 
    <<do something>> 
    END LOOP; 

    FOR b IN (SELECT * 
       FROM dept) 
    LOOP 
    <<do something else>> 
    END LOOP; 
END; 

在这两种情况下,当你退出块Oracle会自动采取关闭游标的照顾。

如果您出于某种原因需要使用显式游标,并且假设您需要捕获多个不同的异常,因为您将以不同的方式处理这些异常,则可以创建一个嵌套块来关闭游标并从每个异常处理程序

DECLARE 
    CURSOR cursor_a 
     IS SELECT * 
      FROM emp; 
    CURSOR cursor_b 
     IS SELECT * 
      FROM dept; 
    PROCEDURE close_open_cursors 
    AS 
    BEGIN 
    IF(cursor_a%isopen) 
    THEN 
     close cursor_a; 
    END IF; 
    IF(cursor_b%isopen) 
    THEN 
     close cursor_b; 
    END IF; 
    END; 
BEGIN 
    OPEN cursor_a; 
    OPEN cursor_b; 
    RAISE no_data_found; 
EXCEPTION 
    WHEN no_data_found 
    THEN 
    close_open_cursors; 
    <<do something meaningful>> 
    WHEN too_many_rows 
    THEN 
    close_open_cursors; 
    <<do something meaningful>> 
    WHEN others 
    THEN 
    close_open_cursors; 
    raise; 
END; 
+0

在某些情况下可能不会。我正在尝试更改现有代码,因此需要时间将所有显式游标更改为隐式。 要解决打开的游标问题,我想通过控制从一个地方关闭现有的游标来最大限度地减少错误的范围。 – ziggy

+0

@ziggy - 发布一个可以从每个异常处理程序调用以关闭所有游标的嵌套块的示例。这至少给你一个位置来放置所有的清理逻辑。 –

+0

是的,应该工作。 我想现在要做的最好的事情是避免显式游标。谢谢! – ziggy