Oracle 游标中的PL/SQL变量是否与绑定参数有效相同?

Oracle 游标中的PL/SQL变量是否与绑定参数有效相同?,oracle,plsql,cursor,bind-variables,parameterbinding,Oracle,Plsql,Cursor,Bind Variables,Parameterbinding,我听说使用绑定变量更有效,因为对于使用不同绑定值的后续调用,查询本身仍然是相同的,因此不再需要对其进行解析 我理解为什么固定值会出现这种情况。在下面的光标中,该值固定为1。如果我有一个相同的不同游标,除了1变为2,它是一个不同的查询。到目前为止还没有 declare cursor C_CURSOR is select * from TESTTABLE pt where pt.ID = 1; 但是我想知道在游标中使用PL/SQL变量时是否也是这样。它们是像固定值一样展开的,还是被解

我听说使用绑定变量更有效,因为对于使用不同绑定值的后续调用,查询本身仍然是相同的,因此不再需要对其进行解析

我理解为什么固定值会出现这种情况。在下面的光标中,该值固定为1。如果我有一个相同的不同游标,除了1变为2,它是一个不同的查询。到目前为止还没有

declare
  cursor C_CURSOR is 
    select * from TESTTABLE pt where pt.ID = 1;
但是我想知道在游标中使用PL/SQL变量时是否也是这样。它们是像固定值一样展开的,还是被解释为绑定变量

我已经搜索了很多地方,但是我到处都能找到关于文字的例子,就像上面的例子一样,但是没有关于PL/SQL变量使用的明确解释

换句话说,在下面的两个片段中,第二个片段可能更有效,还是本质上相同

直接在游标中使用PL/SQL变量:

declare
  V_TEST integer := 1;

  cursor C_CURSOR is 
    select * 
    from 
      TESTTABLE pt
    where
      pt.ID = V_TEST;

begin
  for r in C_CURSOR loop
    null;
  end loop;
end;
使用绑定变量:

declare
  V_TEST int := 1;

  cursor C_CURSOR(B_TEST int) is 
    select * 
    from 
      TESTTABLE pt
    where
      pt.ID = B_TEST;

begin
  for r in C_CURSOR(V_TEST) loop
    null;
  end loop;
end;

首先,好问题

我想引用一句话:

对PL/SQL变量的每个引用实际上都是一个绑定变量

话虽如此

PL/SQL本身负责处理与绑定变量相关的大多数问题,您编写的大多数代码都已经在不知不觉中使用了绑定变量。以PL/SQL的以下位为例:

create or replace procedure dsal(p_empno in number)
as
  begin
    update emp
    set sal=sal*2
    where empno = p_empno;
    commit;
  end;
/
现在,您可能会认为必须用bind变量替换p_empno。然而,好消息是,对PL/SQL变量的每个引用实际上都是一个绑定变量

阅读精细手册:

PL/SQL静态SQL语句可以有PL/SQL标识符,只要它的SQL对应项可以有绑定变量的占位符。PL/SQL标识符必须标识变量或形式参数

从SQL引擎的角度来看,您的两个示例代码段都是等效的,并且性能相同

阅读更多相同的精细手册:

通常,PL/SQL仅在会话第一次打开显式游标时解析它,并且仅在语句第一次运行时解析SQL语句(创建隐式游标)

所有解析的SQL语句都被缓存。只有当SQL语句被新的SQL语句从缓存中过时时,才会重新解析SQL语句。尽管必须先关闭显式游标,然后才能重新打开它,但PL/SQL不需要重新分析关联的查询。如果关闭并立即重新打开显式游标,PL/SQL不会重新分析关联查询

因此,更改绑定变量不需要SQL语句解析


从代码可读性(即维护)的角度来看,使用的第二个代码段更优越。这在小代码段中并不明显,但在大型PL/SQL程序中,如果游标直接使用包或子例程变量,则会令人头痛。阅读代码时,每次都需要检查光标所依赖的状态。使用游标参数可以立即看到这一点。

查找游标共享参数。是的,对PL/SQL变量的每个引用实际上都是一个绑定变量。@ruudvan我找到了。我在寻找答案时发现了这一点,但它只与我的问题有着千丝万缕的联系。游标共享与绑定窥视和性能问题更相关。不要忘记,它是针对11g及以上版本的,因为它是在11g中引入的。@LalitKumarB,你完全正确。我只是在我已经评论过之后才意识到。我不想删除它,以防有人通过sql而不是pl/sql来这里:)这正是我的想法和希望。我就是找不到证明它的文件。非常感谢你提供了这一点。