为什么使用显式游标而不是常规循环?

ini*_*ini 12 oracle plsql

我已经写了一年的基本 Web 应用程序(用于 Oracle 数据库),并且由于函数非常简单,我们大多数人都坚持使用常规 FOR 循环来获取我们的数据:

for i in (select * from STUDENTS) loop
      htp.prn(i.student_last_name || ', ' || i.student_first_name || ' ' || i.student_dob);
end loop;
Run Code Online (Sandbox Code Playgroud)

但是,游标似乎是做事的“正确”方式。我可以找到很多关于游标是什么以及遍历它们的不同方法的信息,但是我找不到在常规 FOR 循环上使用它们的可靠理由。它是否取决于程序的需要?是否有我应该注意的固有优势?

Jus*_*ave 16

您发布的代码正在使用游标。它使用隐式游标循环。

在某些情况下,使用显式游标循环(即在声明部分声明 CURSOR 变量)会产生更清晰的代码或更好的性能

  1. 如果您有无法重构为视图的更复杂的查询,如果您的循环迭代,它可以使代码更易于阅读 student_cursor而不是包括嵌入一堆逻辑的 30 行 SQL 语句。例如,如果您要打印所有已获准毕业的学生,​​并且需要加入包含其学术记录、学位课程要求的表格、包含学术保留信息的表格、包含过期图书馆书籍信息的表格、包含有关未付费用、管理覆盖等信息的表。重构代码可能是有意义的,这样该查询就不会卡在与向用户呈现列表有关的代码中间。这可能涉及创建一个视图来封装所有这些逻辑。或者它可能涉及创建一个显式游标,该游标被声明为当前 PL/SQL 块的一部分或一些更高级别的 PL/SQL 块(即 在包中声明的游标),以便它可以重用。或者它可能涉及为封装和可重用性做一些其他事情(例如,创建一个流水线表函数)。
  2. 如果要在 PL/SQL 中使用批量操作,通常要使用显式游标。这是一个 StackOverflow 线程,它讨论了显式和隐式游标之间性能差异。如果您所做的只是调用htp.prn,那么执行 aBULK COLLECT可能不会给您带来任何好处。但是,在其他情况下,它可以导致显着的性能改进。


Lei*_*fel 7

游标可以是显式的或隐式的,并且可以在 FOR 循环中使用任一类型。你的问题实际上有两个方面。

  1. 为什么在隐式游标 FOR 循环上使用显式游标 FOR 循环?

    • 当查询将被重用时使用显式游标 FOR 循环,否则首选隐式游标。
  2. 为什么使用带有 FETCH 的循环而不是没有显式 FETCH 的 FOR 循环?

    • 当您需要批量收集或需要动态 SQL 时,请在循环内使用 FETCH。

以下是文档中的一些有用信息。

FOR LOOP 隐式游标示例

BEGIN
   FOR vItems IN (
      SELECT last_name
      FROM employees
      WHERE manager_id > 120
      ORDER BY last_name
   ) 
   LOOP
      DBMS_OUTPUT.PUT_LINE ('Name = ' || vItems.last_name);
   END LOOP;
END;
/
Run Code Online (Sandbox Code Playgroud)

显式游标 FOR LOOP 示例

DECLARE
   CURSOR c1 IS
      SELECT last_name
      FROM employees
      WHERE manager_id > 120
      ORDER BY last_name;
BEGIN
   FOR vItems IN c1 LOOP
      DBMS_OUTPUT.PUT_LINE ('Name = ' || vItems.last_name);
   END LOOP;
END;
/
Run Code Online (Sandbox Code Playgroud)

隐式光标

隐式游标是由 PL/SQL 构造和管理的会话游标。每次运行 SELECT 或 DML 语句时,PL/SQL 都会打开一个隐式游标。您无法控制隐式游标,但可以从其属性中获取信息。

隐式游标在其关联语句运行后关闭;但是,它的属性值在另一个 SELECT 或 DML 语句运行之前一直可用。

隐式游标属性为:SQL%ISOPEN、SQL%FOUND、SQL%NOTFOUND、SQL%ROWCOUNT、SQL%BULK_ROWCOUNT、SQL%BULK_EXCEPTIONS

显式光标

显式游标是您构造和管理的会话游标。您必须声明并定义一个显式游标,为其指定名称并将其与查询相关联(通常,查询返回多行)。然后您可以通过以下任一方式处理查询结果集:

打开显式游标(使用 OPEN 语句),从结果集中提取行(使用 FETCH 语句),然后关闭显式游标(使用 CLOSE 语句)。

在游标 FOR LOOP 语句中使用显式游标(请参阅“使用游标 FOR LOOP 语句处理查询结果集”)。

您不能为显式游标赋值,不能在表达式中使用它,也不能将其用作正式的子程序参数或主变量。您可以使用游标变量来完成这些操作(请参阅“游标变量”)。

与隐式游标不同,您可以通过名称引用显式游标或游标变量。因此,显式游标或游标变量称为命名游标。

光标 FOR LOOP 语句

游标 FOR LOOP 语句允许您运行 SELECT 语句,然后立即循环遍历结果集的行。此语句可以使用隐式或显式游标。