Are PL/SQL variables in cursors effectively the same as bind parameters?

一曲冷凌霜 提交于 2019-11-28 05:04:05

问题


I've heard that using bind variables is (can be) more efficient, because for subsequent calls with a different bind value, the query itself is still the same, so it doesn't need to be parsed anymore.

I understand why this is the case for fixed values. In the cursor below, the value is fixed on 1. If I have a different cursor that is the same, except the 1 becomes 2, it is a diffent query. Clear so far.

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

But I wondered if this is also the case when using PL/SQL variables inside the cursor. Are they expanded as if it's a fixed value, or are they interpreted as bind variables.

I've searched far and wide, but everywhere I find examples about literals, as in the case above, but no clear explanation about the use of PL/SQL variables.

In other words, of the two snippets below, is the second one potentially more efficient, or are they essentially the same?

With a PL/SQL variable directly in the cursor:

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;

With a bind variable:

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;

回答1:


First of all, good question.

I would like to make a small quote:

Every reference to a PL/SQL variable is in fact a bind variable.

Having said that,

PL/SQL itself takes care of most of the issues to do with bind variables, to the point where most code that you write already uses bind variables without you knowing. Take, for example, the following bit of 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;
/

Now you might be thinking that you've got to replace the p_empno with a bind variable. However, the good news is that every reference to a PL/SQL variable is in fact a bind variable.

Source




回答2:


Reading the fine manual: PL/SQL Static SQL

A PL/SQL static SQL statement can have a PL/SQL identifier wherever its SQL counterpart can have a placeholder for a bind variable. The PL/SQL identifier must identify either a variable or a formal parameter.

Both of your example snippets are equivalent from SQL engine point of view and perform equally well.

Reading more the same fine manual:

Generally, PL/SQL parses an explicit cursor only the first time the session opens it and parses a SQL statement (creating an implicit cursor) only the first time the statement runs.

All parsed SQL statements are cached. A SQL statement is reparsed only if it is aged out of the cache by a new SQL statement. Although you must close an explicit cursor before you can reopen it, PL/SQL need not reparse the associated query. If you close and immediately reopen an explicit cursor, PL/SQL does not reparse the associated query.

So changing the bind variable requires no SQL statement parsing.

From code readability (i.e. maintenance) point of view the second snippet that is using parameters is superior. It's not obvious in small snippets but in large PL/SQL programs it's a headache if cursors directly use package or subroutine variables. When reading code one needs every time check what is the state the cursor depends on. With cursor parameters one sees that immediatelly.



来源:https://stackoverflow.com/questions/29774122/are-pl-sql-variables-in-cursors-effectively-the-same-as-bind-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!