简体   繁体   English

PL/SQL 中参数化游标的意义何在?

[英]What's the point of parameterized cursors in PL/SQL?

Could someone explain what's the point of using a parameterized cursor in PL/SQL instead of just creating a variable and using that inside?有人能解释一下在 PL/SQL 中使用参数化游标而不是仅仅创建一个变量并在内部使用它的意义何在?

The following anonymous block shows what I mean:以下匿名块显示了我的意思:

DECLARE
    num NUMBER := 1;
    CURSOR d1 (p_num IN NUMBER) IS SELECT 'foo' FROM dual WHERE 1 = p_num;
    CURSOR d2 IS SELECT 'foo' FROM dual WHERE 1 = num;
BEGIN
    NULL;
END;

Is there any kind of difference in processing/performance/etc between cursors d1 and d2?游标 d1 和 d2 之间在处理/性能/等方面有什么不同吗?

Thanks in advance.提前致谢。

You might not know your p_num value until runtime.您可能直到运行时才知道您的p_num值。 It might be something you get from other processing, or another table, or the client environment, or calculate somehow.它可能是您从其他处理、另一个表、客户端环境或以某种方式计算得到的东西。

As a trivial example:作为一个简单的例子:

declare
  cursor c1 is
    select * from departments;
  cursor c2 (p_department_id employees.department_id%type) is
    select * from employees
    where department_id = p_department_id;
begin
  for r1 in c1 loop
    -- do something with this department info
    dbms_output.put_line(r1.department_name);

    -- now loop through empoyees in that department
    for r2 in c2 (r1.department_id) loop
      -- do something with this employee info
      dbms_output.put_line('  ' || r2.first_name);
    end loop;
  end loop;
end;
/

Administration
  Jennifer
Marketing
  Michael
  Pat
Purchasing
  Den
  Alexander
...

The c2 cursor is looking for employees in a single department, but that can't be hard-coded. c2游标正在寻找单个部门中的员工,但不能进行硬编码。

You could do the same thing with the equivalent of your d2 construct, ie assigning a separate local variable which the inner cursor will still use - since it's being reopened and evaluates the variable at that point:您可以使用d2构造的等效项执行相同的操作,即分配一个单独的局部变量,内部游标仍将使用该变量 - 因为它正在重新打开并在此时评估变量:

declare
  l_department_id departments.department_id%type;
  cursor c1 is
    select * from departments;
  cursor c2 is
    select * from employees
    where department_id = l_department_id;
begin
  for r1 in c1 loop
    -- do something with this department info
    dbms_output.put_line(r1.department_name);
    -- ...

    -- now loop through empoyees in that department
    l_department_id := r1.department_id;
    for r2 in c2 loop
      -- do something with this employee info
      dbms_output.put_line('  ' || r2.first_name);
    end loop;
  end loop;
end;
/

... but having a parameter makes it clearer that the value is expected to change, and avoids the possibility of making two calls and forgetting to change the value in between. ...但有一个参数可以更清楚地表明该值预计会发生变化,并避免了两次调用而忘记更改中间值的可能性。

In both cases the actual SQL of the cursor query will be treated as having a bind variable;在这两种情况下,游标查询的实际 SQL 将被视为具有绑定变量; the difference is just how that is populated.不同之处在于它是如何填充的。


Clearly you wouldn't really do this particular task with nested loops, or any PL/SQL;很明显,您不会真正使用嵌套循环或任何 PL/SQL 来执行此特定任务; and in a lot of places this kind of construct is used the same applies, or the queries could at least be combined into a single cursor with a join.并且在很多地方使用这种构造也同样适用,或者查询至少可以通过连接组合成单个游标。

It can still be useful for more complicated logic, eg where there are several paths the code could take and multiple optional secondary cursors, and all need information from the same (expensive) base query, and you don't want to repeatedly join to the base tables.对于更复杂的逻辑,它仍然很有用,例如,代码可以采用多条路径和多个可选的辅助游标,并且都需要来自相同(昂贵)基本查询的信息,并且您不想重复加入到基表。

As with most row-by-row processing I suspect it's misused more often than it's genuinely necessary.与大多数逐行处理一样,我怀疑它被滥用的频率比真正必要的要高。 It's still a useful tool to have available though.尽管如此,它仍然是一个有用的工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM