0% found this document useful (0 votes)
2 views

Dynamic SQL

Dynamic SQL allows for the execution of SQL statements that are not fully known until runtime, providing flexibility over static SQL, which is fixed at compile time. It can be implemented using either the DBMS_SQL package or native dynamic SQL, with the latter being easier and faster to use. The document outlines the advantages and disadvantages of both methods, including performance considerations and support for various SQL features.

Uploaded by

Muhammad
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Dynamic SQL

Dynamic SQL allows for the execution of SQL statements that are not fully known until runtime, providing flexibility over static SQL, which is fixed at compile time. It can be implemented using either the DBMS_SQL package or native dynamic SQL, with the latter being easier and faster to use. The document outlines the advantages and disadvantages of both methods, including performance considerations and support for various SQL features.

Uploaded by

Muhammad
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 8

Dynamic SQL

By Muhammad Raheem [email protected]

What Is Dynamic SQL?

Dynamic SQL enables you to write programs that reference SQL statements whose full text is not known
until runtime. Before discussing dynamic SQL in detail, a clear definition of static SQL may provide a good
starting point for understanding dynamic SQL. Static SQL statements do not change from execution to
execution. The full text of static SQL statements are known at compilation, which provides the following
benefits:

 Successful compilation verifies that the SQL statements reference valid database objects.
 Successful compilation verifies that the necessary privileges are in place to access the database
objects.
 Performance of static SQL is generally better than dynamic SQL.

Because of these advantages, you should use dynamic SQL only if you cannot use static SQL to
accomplish your goals, or if using static SQL is cumbersome compared to dynamic SQL. However, static
SQL has limitations that can be overcome with dynamic SQL. You may not always know the full text of
the SQL statements that must be executed in a PL/SQL procedure. Your program may accept user input
that defines the SQL statements to execute, or your program may need to complete some processing
work to determine the correct course of action. In such cases, you should use dynamic SQL.

Dynamic SQL also lets you execute data definition language (DDL) statements and other SQL statements
that are not supported in purely static SQL programs.

Dynamic SQL:
 Is a SQL statement that contains variables that can change during runtime
 Is a SQL statement with placeholders and is stored as a character string
 Enables general-purpose code to be written
 Enables data-definition, data-control, or sessioncontrol statements to be written and executed from
PL/SQL
 Is written using either DBMS_SQL or native dynamic SQL

Using the DBMS_SQL Package


The DBMS_SQL package is used to write dynamic SQL in stored procedures and to parse DDL
statements.
Some of the procedures and functions of the package include:
– OPEN_CURSOR
– PARSE
– BIND_VARIABLE
– EXECUTE
– FETCH_ROWS
– CLOSE_CURSOR

Choosing Between Native Dynamic SQL and the DBMS_SQL Package


Oracle provides two methods for using dynamic SQL within PL/SQL: native dynamic SQL and the
DBMS_SQL package. Native dynamic SQL lets you place dynamic SQL statements directly into PL/SQL
code. These dynamic statements include DML statements (including queries), PL/SQL anonymous
blocks, DDL statements, transaction control statements, and session control statements.

To process most native dynamic SQL statements, you use the EXECUTE IMMEDIATE statement. To
process a multi-row query (SELECT statement), you use OPEN-FOR, FETCH, and CLOSE statements.
The DBMS_SQL package is a PL/SQL library that offers an API to execute SQL statements dynamically.
The DBMS_SQL package has procedures to open a cursor, parse a cursor, supply binds, and so on.
Programs that use the DBMS_SQL package make calls to this package to perform dynamic SQL
operations.

The following sections provide detailed information about the advantages of both methods.

1
Dynamic SQL
By Muhammad Raheem [email protected]
Advantages of Native Dynamic SQL

Native dynamic SQL provides the following advantages over the DBMS_SQL package:

Native Dynamic SQL is Easy to Use


Because native dynamic SQL is integrated with SQL, you can use it in the same way that you use static
SQL within PL/SQL code. Native dynamic SQL code is typically more compact and readable than
equivalent code that uses the DBMS_SQL package.

With the DBMS_SQL package you must call many procedures and functions in a strict sequence, making
even simple operations require a lot of code. You can avoid this complexity by using native dynamic SQL
instead.

The following table illustrates the difference in the amount of code required to perform the same operation
using the DBMS_SQL package and native dynamic SQL.

Code Comparison of DBMS_SQL Package and Native Dynamic SQL


DBMS_SQL Package Native Dynamic SQL
CREATE PROCEDURE insert_into_table ( CREATE PROCEDURE insert_into_table (
table_name VARCHAR2, table_name VARCHAR2,
deptnumber NUMBER, deptnumber NUMBER,
deptname VARCHAR2, deptname VARCHAR2,
location VARCHAR2) IS location VARCHAR2) IS
cur_hdl INTEGER; stmt_str VARCHAR2(200);
stmt_str VARCHAR2(200);
rows_processed BINARY_INTEGER; BEGIN
stmt_str := 'INSERT INTO ' ||
BEGIN table_name || ' values
stmt_str := 'INSERT INTO ' || (:deptno, :dname, :loc)';
table_name || ' VALUES
(:deptno, :dname, :loc)'; EXECUTE IMMEDIATE stmt_str
USING
-- open cursor deptnumber, deptname, location;
cur_hdl := dbms_sql.open_cursor;
END;
-- parse cursor /
dbms_sql.parse(cur_hdl, stmt_str, SHOW ERRORS;
dbms_sql.native);

-- supply binds
dbms_sql.bind_variable
(cur_hdl, ':deptno', deptnumber);
dbms_sql.bind_variable
(cur_hdl, ':dname', deptname);
dbms_sql.bind_variable
(cur_hdl, ':loc', location);

-- execute cursor
rows_processed :=
dbms_sql.execute(cur_hdl);

-- close cursor
dbms_sql.close_cursor(cur_hdl);

END;
/
SHOW ERRORS;

2
Dynamic SQL
By Muhammad Raheem [email protected]

Native Dynamic SQL is Faster than DBMS_SQL


Native dynamic SQL in PL/SQL performs comparably to the performance of static SQL, because the
PL/SQL interpreter has built-in support for it. Programs that use native dynamic SQL are much faster than
programs that use the DBMS_SQL package. Typically, native dynamic SQL statements perform 1.5 to 3
times better than equivalent DBMS_SQL calls. (Your performance gains may vary depending on your
application.)

Native dynamic SQL bundles the statement preparation, binding, and execution steps into a single
operation, which minimizes the data copying and procedure call overhead and improves performance.

The DBMS_SQL package is based on a procedural API and incurs high procedure call and data copy
overhead. Each time you bind a variable, the DBMS_SQL package copies the PL/SQL bind variable into
its space for use during execution. Each time you execute a fetch, the data is copied into the space
managed by the DBMS_SQL package and then the fetched data is copied, one column at a time, into the
appropriate PL/SQL variables, resulting in substantial overhead.

Performance Tip: Using Bind Variables


When using either native dynamic SQL or the DBMS_SQL package, you can improve performance by
using bind variables, because bind variables allow Oracle to share a single cursor for multiple SQL
statements.

For example, the following native dynamic SQL code does not use bind variables:
CREATE OR REPLACE PROCEDURE del_dept (
my_deptno dept.deptno%TYPE) IS
BEGIN
EXECUTE IMMEDIATE 'DELETE FROM dept WHERE deptno = ' || to_char
(my_deptno);
END;
/
SHOW ERRORS;

For each distinct my_deptno variable, a new cursor is created, causing resource contention and poor
performance. Instead, bind my_deptno as a bind variable:
CREATE OR REPLACE PROCEDURE del_dept (
my_deptno dept.deptno%TYPE) IS
BEGIN
EXECUTE IMMEDIATE 'DELETE FROM dept WHERE deptno = :1' USING my_deptno;
END;
/
SHOW ERRORS;

Here, the same cursor is reused for different values of the bind my_deptno, improving performance and
scalabilty.

Native Dynamic SQL Supports User-Defined Types


Native dynamic SQL supports all of the types supported by static SQL in PL/SQL, including user-defined
types such as user-defined objects, collections, and REFs. The DBMS_SQL package does not support
these user-defined types.

Native Dynamic SQL Supports Fetching Into Records


Native dynamic SQL and static SQL both support fetching into records, but the DBMS_SQL package
does not. With native dynamic SQL, the rows resulting from a query can be directly fetched into PL/SQL
records.

In the following example, the rows from a query are fetched into the emp_rec record:
DECLARE
TYPE EmpCurTyp IS REF CURSOR;
c EmpCurTyp;
emp_rec emp%ROWTYPE;

3
Dynamic SQL
By Muhammad Raheem [email protected]
stmt_str VARCHAR2(200);
e_job emp.job%TYPE;

BEGIN
stmt_str := 'SELECT * FROM emp WHERE job = :1';
-- in a multi-row query
OPEN c FOR stmt_str USING 'MANAGER';
LOOP
FETCH c INTO emp_rec;
EXIT WHEN c%NOTFOUND;
END LOOP;
CLOSE c;
-- in a single-row query
EXECUTE IMMEDIATE stmt_str INTO emp_rec USING 'PRESIDENT';

END;
/

Advantages of the DBMS_SQL Package


The DBMS_SQL package provides the following advantages over native dynamic SQL:

DBMS_SQL is Supported in Client-Side Programs


The DBMS_SQL package is supported in client-side programs, but native dynamic SQL is not. Every call
to the DBMS_SQL package from the client-side program translates to a PL/SQL remote procedure call
(RPC); these calls occur when you need to bind a variable, define a variable, or execute a statement.

DBMS_SQL Supports DESCRIBE


The DESCRIBE_COLUMNS procedure in the DBMS_SQL package can be used to describe the columns
for a cursor opened and parsed through DBMS_SQL. This feature is similar to the DESCRIBE command
in SQL*Plus. Native dynamic SQL does not have a DESCRIBE facility.

DBMS_SQL Supports Multiple Row Updates and Deletes with a RETURNING Clause
The DBMS_SQL package supports statements with a RETURNING clause that update or delete multiple
rows. Native dynamic SQL only supports a RETURNING clause if a single row is returned.

DBMS_SQL Supports SQL Statements Larger than 32KB


The DBMS_SQL package supports SQL statements larger than 32KB; native dynamic SQL does not.

DBMS_SQL Lets You Reuse SQL Statements


The PARSE procedure in the DBMS_SQL package parses a SQL statement once. After the initial
parsing, you can use the statement multiple times with different sets of bind arguments.

Native dynamic SQL prepares a SQL statement each time the statement is used, which typically involves
parsing, optimization, and plan generation. Although the extra prepare operations incur a small
performance penalty, the slowdown is typically outweighed by the performance benefits of native dynamic
SQL.

Examples of DBMS_SQL Package Code and Native Dynamic SQL Code


The following examples illustrate the differences in the code necessary to complete operations with the
DBMS_SQL package and native dynamic SQL. Specifically, the following types of examples are
presented:
 A query
 A DML operation
 A DML returning operation

In general, the native dynamic SQL code is more readable and compact, which can improve developer
productivity.

4
Dynamic SQL
By Muhammad Raheem [email protected]
Querying Using Dynamic SQL: Example
The following example includes a dynamic query statement with one bind variable (:jobname) and two
select columns (ename and sal):
stmt_str := 'SELECT ename, sal FROM emp WHERE job = :jobname';

This example queries for employees with the job description SALESMAN in the job column of the emp
table. The following table shows sample code that accomplishes this query using the DBMS_SQL
package and native dynamic SQL.

Querying Using the DBMS_SQL Package and Native Dynamic SQL


DBMS_SQL Query Operation Native Dynamic SQL Query Operation
DECLARE DECLARE
stmt_str varchar2(200); TYPE EmpCurTyp IS REF CURSOR;
cur_hdl int; cur EmpCurTyp;
rows_processed int; stmt_str VARCHAR2(200);
name varchar2(10); name VARCHAR2(20);
salary int; salary NUMBER;
BEGIN BEGIN
cur_hdl := dbms_sql.open_cursor; -- open stmt_str := 'SELECT ename, sal
cursor FROM emp
stmt_str := 'SELECT ename, sal FROM emp WHERE job = :1';
WHERE OPEN cur FOR stmt_str USING
job = :jobname'; 'SALESMAN';
dbms_sql.parse(cur_hdl, stmt_str,
dbms_sql.native); LOOP
FETCH cur INTO name, salary;
-- supply binds (bind by name) EXIT WHEN cur%NOTFOUND;
dbms_sql.bind_variable( -- <process data>
cur_hdl, 'jobname', 'SALESMAN'); END LOOP;
CLOSE cur;
-- describe defines END;
dbms_sql.define_column(cur_hdl, 1, name, /
200);
dbms_sql.define_column(cur_hdl, 2,
salary);

rows_processed :=
dbms_sql.execute(cur_hdl); --
execute

LOOP
-- fetch a row
IF dbms_sql.fetch_rows(cur_hdl) > 0 then

-- fetch columns from the row


dbms_sql.column_value(cur_hdl, 1,
name);
dbms_sql.column_value(cur_hdl, 2,
salary);

-- <process data>

ELSE
EXIT;
END IF;
END LOOP;
dbms_sql.close_cursor(cur_hdl); -- close
cursor
END;

5
Dynamic SQL
By Muhammad Raheem [email protected]

DBMS_SQL Query Operation Native Dynamic SQL Query Operation


/

Performing DML Using Dynamic SQL: Example


The following example includes a dynamic INSERT statement for a table with three columns:
stmt_str := 'INSERT INTO dept_new VALUES (:deptno, :dname, :loc)';

This example inserts a new row for which the column values are in the PL/SQL variables deptnumber,
deptname, and location. The following table shows sample code that accomplishes this DML operation
using the DBMS_SQL package and native dynamic SQL.

DML Operation Using the DBMS_SQL Package and Native Dynamic SQL
DBMS_SQL DML Operation Native Dynamic SQL DML Operation
DECLARE DECLARE
stmt_str VARCHAR2(200); stmt_str VARCHAR2(200);
cur_hdl NUMBER; deptnumber NUMBER := 99;
deptnumber NUMBER := 99; deptname VARCHAR2(20);
deptname VARCHAR2(20); location VARCHAR2(10);
location VARCHAR2(10); BEGIN
rows_processed NUMBER; stmt_str := 'INSERT INTO
BEGIN dept_new VALUES
stmt_str := 'INSERT INTO dept_new VALUES (:deptno, :dname, :loc)';
(:deptno, :dname, :loc)'; EXECUTE IMMEDIATE stmt_str
cur_hdl := DBMS_SQL.OPEN_CURSOR; USING deptnumber, deptname,
DBMS_SQL.PARSE( location;
cur_hdl, stmt_str, DBMS_SQL.NATIVE); END;
-- supply binds /
DBMS_SQL.BIND_VARIABLE
(cur_hdl, ':deptno', deptnumber);
DBMS_SQL.BIND_VARIABLE
(cur_hdl, ':dname', deptname);
DBMS_SQL.BIND_VARIABLE
(cur_hdl, ':loc', location);
rows_processed :=
dbms_sql.execute(cur_hdl);
-- execute
DBMS_SQL.CLOSE_CURSOR(cur_hdl); -- close
END;
/

Performing DML with RETURNING Clause Using Dynamic SQL: Example


The following example uses a dynamic UPDATE statement to update the location of a department, then
returns the name of the department:
stmt_str := 'UPDATE dept_new
SET loc = :newloc
WHERE deptno = :deptno
RETURNING dname INTO :dname';

The following table shows sample code that accomplishes this operation using both the DBMS_SQL
package and native dynamic SQL.

DML Returning Operation Using the DBMS_SQL Package and Native Dynamic SQL

6
Dynamic SQL
By Muhammad Raheem [email protected]

Native Dynamic SQL DML Returning


DBMS_SQL DML Returning Operation Operation
DECLARE DECLARE
deptname_array deptname_array
dbms_sql.Varchar2_Table; dbms_sql.Varchar2_Table;
cur_hdl INT; stmt_str VARCHAR2(200);
stmt_str VARCHAR2(200); location VARCHAR2(20);
location VARCHAR2(20); deptnumber NUMBER := 10;
deptnumber NUMBER := 10; deptname VARCHAR2(20);
rows_processed NUMBER; BEGIN
BEGIN stmt_str := 'UPDATE dept_new
stmt_str := 'UPDATE dept_new SET loc = :newloc
SET loc = :newloc WHERE deptno = :deptno
WHERE deptno = :deptno RETURNING dname INTO :dname';
RETURNING dname INTO :dname'; EXECUTE IMMEDIATE stmt_str
USING location, deptnumber, OUT
cur_hdl := dbms_sql.open_cursor; deptname;
dbms_sql.parse END;
(cur_hdl, stmt_str, /
dbms_sql.native);
-- supply binds
dbms_sql.bind_variable
(cur_hdl, ':newloc', location);
dbms_sql.bind_variable
(cur_hdl, ':deptno', deptnumber);
dbms_sql.bind_array
(cur_hdl, ':dname',
deptname_array);
-- execute cursor
rows_processed :=
dbms_sql.execute(cur_hdl);
-- get RETURNING column into OUT bind
array
dbms_sql.variable_value
(cur_hdl, ':dname',
deptname_array);
dbms_sql.close_cursor(cur_hdl);
END;
/

Using Dynamic SQL in Languages Other Than PL/SQL


Although this chapter discusses PL/SQL support for dynamic SQL, you can call dynamic SQL from other
languages:
 If you use C/C++, you can call dynamic SQL with the Oracle Call Interface (OCI), or you can use
the Pro*C/C++ precompiler to add dynamic SQL extensions to your C code.
 If you use COBOL, you can use the Pro*COBOL precompiler to add dynamic SQL extensions to
your COBOL code.
 If you use Java, you can develop applications that use dynamic SQL with JDBC.

If you have an application that uses OCI, Pro*C/C++, or Pro*COBOL to execute dynamic SQL, you
should consider switching to native dynamic SQL inside PL/SQL stored procedures and functions. The
network round-trips required to perform dynamic SQL operations from client-side applications might hurt
performance. Stored procedures can reside on the server, eliminating the network overhead. You can call
the PL/SQL stored procedures and stored functions from the OCI, Pro*C/C++, or Pro*COBOL application.

Using PL/SQL Records in SQL INSERT and UPDATE Statements

7
Dynamic SQL
By Muhammad Raheem [email protected]
Although you can enumerate each field of a PL/SQL record when inserting or updating rows in a table,
the resulting code is not especially readable or maintainable. Instead, you can use PL/SQL records
directly in these statements. The most convenient technique is to declare the record using a %ROWTYPE
attribute, so that it has exactly the same fields as the SQL table.

DECLARE
emp_rec emp%ROWTYPE;
BEGIN
emp_rec.eno := 1500;
emp_rec.ename := 'Steven Hill';
emp_rec.sal := '40000';
-- A %ROWTYPE value can fill in all the row fields.
INSERT INTO emp VALUES emp_rec;

-- The fields of a %ROWTYPE can completely replace the table columns.


UPDATE emp SET ROW = emp_rec WHERE eno = 100;
END;
/

Although this technique helps to integrate PL/SQL variables and types more closely with SQL DML
statements, you cannot use PL/SQL records as bind variables in dynamic SQL statements.

You might also like