如何在 PLSQL 中释放游标?

Posted

技术标签:

【中文标题】如何在 PLSQL 中释放游标?【英文标题】:How to deallocate cursor in PLSQL? 【发布时间】:2014-10-24 23:09:37 【问题描述】:

我在 SQL Server 和 Oracle 上都编写代码。 当我在 SQL Server 中编码时,我使用了这个:

OPEN curUSERS;
CLOSE curUSERS;
DEALLOCATE curUSERS;

现在,当我在 Oracle 中编码时,我使用了这个:

OPEN curUSERS;
CLOSE curUSERS;

我在 PL/SQL 中看到了一个 DEALLOCATE 关键字,但是当我使用这个语句时

DEALLOCATE(curUSERS);

它会抛出一个错误。如何在 PL/SQL 中做同样的事情(解除分配)?

【问题讨论】:

如果它是一个关键字,我希望调用类似于 OPEN 和 CLOSE,例如DEALLOCATE curUSERS 不带括号。但我从未见过或使用过这个。您能否编辑问题并为此提供指向 Oracle 文档的链接?谢谢。 你有幻觉! Oracle PL/SQL 没有 deallocate 关键字:Oracle 11.2 PL/SQL Reserved Words and Keywords。我不知道 SQL Server,但在 Oracle 中关闭/解除分配/清理游标是一步操作:close 【参考方案1】:

Oracle 不需要显式释放游标的内存。 CLOSE(cursor) 就可以了。

【讨论】:

这有点误导。在显式清除游标(或关闭会话)之前,不会释放显式打开的游标使用的内存。在 Oracle 术语中,清理阶段是关闭 这个答案是正确的。小补充(See docs)。您可以调用close 显式关闭游标并释放其资源。如果您没有显式调用close,则游标将在声明它的块的末尾关闭(对于在程序块/方法中声明的游标),或者在会话结束时(对于在包级别)。【参考方案2】:

应尽可能避免使用显式游标。显式游标需要更多代码并且速度较慢,因为它们不会自动批量收集。光标 FOR 循环既简单又快速。

示例架构

drop table table1;
create table table1 as select 1 a from dual;

显式游标 - 更多代码,性能更差

declare
    v_a number;
    cursor table1_cursor is select a from table1;
begin
    open table1_cursor;
    loop
        fetch table1_cursor into v_a;
        exit when table1_cursor%notfound;
        dbms_output.put_line(v_a);
    end loop;
    close table1_cursor;
end;
/

循环游标 - 更少的代码,更好的性能

begin
    for table1_rows in (select a from table1)
    loop
        dbms_output.put_line(table1_rows.a);    
    end loop;
end;
/

【讨论】:

for 循环仍然不如 forall 的批量收集效率高。如果性能是最终目标,那么首先要摆脱循环。 @LalitKumarB 是的,如果可能,没有循环会更好。问题只是直接关于读取数据,其中 for 循环与任何显式批量收集一样有效。阅读和写作经常一起出现,但根据我的经验,阅读通常比写作多得多,并且在阅读时自动批量收集就足够了。 我们需要写显式游标,即使是批量收集;使用限制子句 @RamDwivedi Cursor for 循环也可以为您解决这个问题。他们自动使用 100 的限制。 @RamDwivedi 100 在理论上和practice 中都适用于任何大小。批量收集通过消除 SQL 和 PL/SQL 之间的切换来节省处理时间。限制为 2 减少了 50% 的开销,3 减少了 66% 等。当限制达到 100 时,剩下的开销不到 1% 需要消除。即使对于大型数据集,从 100 移动到 100,000,000 也几乎没有优势。

以上是关于如何在 PLSQL 中释放游标?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 plsql 函数创建和返回游标?

如何将日期值传递给 plsql 中的游标?

如何从从 plsql 函数 ORACLE 返回的游标中进行选择

如何探索 PLSQL 块中的 out 游标参数?

游标 PLSQL 中的动态列名

PLSQL游标批量更新数据问题