PL/SQL 中的参数化游标有什么意义?
What's the point of parameterized cursors in PL/SQL?
有人可以解释一下在 PL/SQL 中使用参数化游标而不是仅仅创建一个变量并在其中使用它有什么意义吗?
以下匿名块说明了我的意思:
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;
游标 d1 和 d2 之间 processing/performance/etc 有什么区别吗?
提前致谢。
您可能直到运行时才知道您的 p_num
值。它可能是您从其他处理或另一个 table 或客户端环境或以某种方式计算得到的东西。
举个简单的例子:
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
...
c2
游标正在寻找单个部门的员工,但这不能硬编码。
你可以用你的 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;
/
...但是有一个参数可以更清楚地表明预期值会发生变化,并避免进行两次调用而忘记在两者之间更改值的可能性。
在这两种情况下,游标查询的实际 SQL 将被视为具有绑定变量;不同之处在于它的填充方式。
很明显,您不会真正使用嵌套循环或任何 PL/SQL 来执行此特定任务;并且在很多地方都使用同样适用的这种结构,或者至少可以将查询组合成一个带有连接的游标。
它仍然可以用于更复杂的逻辑,例如其中代码可以采用多条路径和多个可选的辅助游标,并且都需要来自相同(昂贵的)基础查询的信息,并且您不想重复加入基础 tables.
与大多数逐行处理一样,我怀疑它被误用的次数比真正必要的多。不过,它仍然是一个有用的工具。
有人可以解释一下在 PL/SQL 中使用参数化游标而不是仅仅创建一个变量并在其中使用它有什么意义吗?
以下匿名块说明了我的意思:
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;
游标 d1 和 d2 之间 processing/performance/etc 有什么区别吗?
提前致谢。
您可能直到运行时才知道您的 p_num
值。它可能是您从其他处理或另一个 table 或客户端环境或以某种方式计算得到的东西。
举个简单的例子:
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
...
c2
游标正在寻找单个部门的员工,但这不能硬编码。
你可以用你的 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;
/
...但是有一个参数可以更清楚地表明预期值会发生变化,并避免进行两次调用而忘记在两者之间更改值的可能性。
在这两种情况下,游标查询的实际 SQL 将被视为具有绑定变量;不同之处在于它的填充方式。
很明显,您不会真正使用嵌套循环或任何 PL/SQL 来执行此特定任务;并且在很多地方都使用同样适用的这种结构,或者至少可以将查询组合成一个带有连接的游标。
它仍然可以用于更复杂的逻辑,例如其中代码可以采用多条路径和多个可选的辅助游标,并且都需要来自相同(昂贵的)基础查询的信息,并且您不想重复加入基础 tables.
与大多数逐行处理一样,我怀疑它被误用的次数比真正必要的多。不过,它仍然是一个有用的工具。