You are on page 1of 3

Bind Variables and Dynamic SQL

The only time you need to consciously decide to use bind variables when working with PL/SQL
is when using Dynamic SQL.

Dynamic SQL, allows you to execute a string containing SQL using the EXECUTE
IMMEDIATE command. For next example would always require a hard parse when it is
submitted:

create or replace procedure dsal(p_empno in number)


as
  begin
    execute immediate
     'update emp set sal = sal*2 where empno = '||p_empno;
  commit;
  end;
/

The way to use bind variables instead is to change the EXECUTE IMMEDIATE command as
follows:

create or replace procedure dsal(p_empno in number)


as
  begin
    execute immediate
     'update emp set
     sal = sal*2 where empno = :x' using p_empno;
  commit;
  end;
/

And that's all there is to it. One thing to bear in mind, though, is that you can't substitute actual
object names (tables, views, columns etc) with bind variables - you can only subsitute literals. If
the object name is generated at runtime, you'll still need to string concatenate these parts, and the
SQL will only match with those already in the shared pool when the same object name comes up.
However, whenever you're using dynamic SQL to build up the predicate part of a statement, use
bind variables instead and you'll reduce dramatically the amount of latch contention going on.

The Performance Killer


Just to give you a tiny idea of how huge of a difference this can make performance wise, you
only need to run a very small test:
Here is the Performance Killer ....

SQL> alter system flush shared_pool;


SQL> set serveroutput on;

declare
      type rc is ref cursor;
      l_rc rc;
      l_dummy all_objects.object_name%type;
      l_start number default dbms_utility.get_time;
  begin
      for i in 1 .. 1000
      loop
          open l_rc for
          'select object_name
             from all_objects
            where object_id = ' || i;
          fetch l_rc into l_dummy;
          close l_rc;
          -- dbms_output.put_line(l_dummy);
      end loop;
      dbms_output.put_line
       (round((dbms_utility.get_time-l_start)/100, 2) ||
        ' Seconds...' );
  end;
/
101.71 Seconds...

... and here is the Performance Winner:

declare
      type rc is ref cursor;
      l_rc rc;
      l_dummy all_objects.object_name%type;
      l_start number default dbms_utility.get_time;
  begin
      for i in 1 .. 1000
      loop
          open l_rc for
          'select object_name
             from all_objects
            where object_id = :x'
          using i;
          fetch l_rc into l_dummy;
          close l_rc;
          -- dbms_output.put_line(l_dummy);
      end loop;
      dbms_output.put_line
       (round((dbms_utility.get_time-l_start)/100, 2) ||
        ' Seconds...' );
end;
/
1.9 Seconds...

That is pretty dramatic.  The fact is that not only does this execute much faster (we spent more
time PARSING our queries then actually EXECUTING them!) it will let more users use your
system simultaneously.

Bind Variables in VB, Java and other applications

The next question is though, what about VB, Java and other applications that fire SQL queries
against an Oracle database. How do these use bind variables? Do you have to in fact split your
SQL into two statements, one to set the bind variable, and one for the statement itself?

In fact, the answer to this is actually quite simple. When you put together an SQL statement
using Java, or VB, or whatever, you usually use an API for accessing the database; ADO in the
case of VB, JDBC in the case of Java. All of these APIs have built-in support for bind
variables, and it's just a case of using this support rather than just concatenating a string
yourself and submitting it to the database.

For example, Java has PreparedStatement, which allows the use of bind variables, and
Statement, which uses the string concatenation approach. If you use the method that supports
bind variables, the API itself passes the bind variable value to Oracle at runtime, and you just
submit your SQL statement as normal. There's no need to separately pass the bind variable value
to Oracle, and actually no additional work on your part. Support for bind variables isn't just
limited to Oracle - it's common to other RDBMS platforms such as Microsoft SQL Server, so
there's no excuse for not using them just because they might be an Oracle-only feature.

You might also like