You are on page 1of 30

Native Dynamic SQL:

A Better Alternative to DBMS_SQL


An Oracle Technical White Paper
March 1999
INTRODUCTION

Dynamic SQL adds power and flexibility to host languages (such as C, COBOL, etc.), by allowing
programs to accept and/or build SQL statements at run time. Dynamic SQL is required to build
applications where the text of the SQL statement is not known until execution time. For example,
dynamic SQL is needed for applications that allow users to choose query search criteria or optimizer
hints at run time. These types of requirements are seen in:

•= Database query tools.

•= Interactive database applications that present the user with information specific to their needs.

•= Application code that is reusable and, therefore, independent of the actual SQL statement
being executed.

Before Oracle8i, PL/SQL programs needed to use the DBMS_SQL package to execute SQL statements
dynamically. This is no longer essential. Native dynamic SQL in PL/SQL is easier to use than
DBMS_SQL, requires much less application code, and performs far better.

The organization of this paper is as follows:

•= A description of the native dynamic SQL capability in PL/SQL.

•= A description of the advantages of using native dynamic SQL. This section will enable the user to
compare it with the DBMS_SQL package approach.

•= Typical usage examples.

•= Important performance tips for using native dynamic SQL.

•= A summary of this feature and future plans in this area.

Native Dynamic SQL: A Better Alternative to DBMS_SQL 2


March 1999
FEATURE DESCRIPTION

Native dynamic SQL provides the ability to dynamically execute SQL statements whose complete
text is not known until execution time. The dynamic statements could be data manipulation
language (DML) statements (including queries), PL/SQL anonymous blocks, data definition language
(DDL) statements, transaction control statements, session control statements, etc.

The following statements have been added/extended in PL/SQL, to support native dynamic SQL:

•= EXECUTE IMMEDIATE — prepares, executes, and deallocates a dynamic SQL statement.

•= OPEN — The syntax of the OPEN cursor statement has been extended. It now supports opening
cursors on a dynamic SQL query that is specified as a string.

•= FETCH, CLOSE — The existing FETCH and CLOSE statements have been extended. They
support dynamic cursors without any syntax changes.

Also, bind arguments can be specified for the dynamic parameters in the EXECUTE IMMEDIATE
and OPEN statements. Native dynamic SQL includes the capability to bind to, or define a dynamic
statement, instances of any SQL data types supported in PL/SQL, and the ability to handle IN, IN
OUT, and OUT bind variables that are bound by position, not by name.

ADVANTAGES OF NATIVE DYNAMIC SQL

Compared to using the DBMS_SQL package, native dynamic SQL has several benefits, including ease
of use, improved performance, and the ability to overcome static SQL and the DBMS_SQL package
limitations. Of the benefits listed below, ease of use and performance provide the most significant
productivity benefits to the end-user.

EASE OF USE

The key motivation for providing native dynamic SQL support in PL/SQL is to make application
development using dynamic SQL statements very easy, compared to using the DBMS_SQL package.
This would be similar to using embedded static SQL statements in PL/SQL today.

Native Dynamic SQL: A Better Alternative to DBMS_SQL 3


March 1999
While DBMS_SQL is a PL/SQL library that offers a programmatic API to execute statements
dynamically, native dynamic SQL is an integral part of PL/SQL. Thus, a native dynamic SQL
program is much more readable and compact than an equivalent program that uses DBMS_SQL.

From looking at the example shown below, current users of the DBMS_SQL package will be able to
immediately see the benefits of this feature.

DML Example using the Equivalent DML Example with


DBMS_SQL package Native Dynamic SQL

procedure insert_into_table (table_name


varchar2, procedure insert_into_table
(table_name varchar2,
deptnumber number, deptname
varchar2, location varchar2) is

cur_hdl integer; deptnumber number, deptname


varchar2, location varchar2) is
stmt_str varchar2(200);

rows_processed binary_integer;
stmt_str varchar2(200);
begin

stmt_str := 'insert into ' ||


begin
table_name || ' values (:deptno,

:dname,
:loc)'; stmt_str := 'insert into ' ||
table_name || ' values (:deptno,

-- open cursor
:dname,
cur_hdl := dbms_sql.open_cursor; :loc)';

-- parse cursor

dbms_sql.parse(cur_hdl, stmt_str,
dbms_sql.native);

Native Dynamic SQL: A Better Alternative to DBMS_SQL 4


March 1999
EXECUTE IMMEDIATE stmt_str
-- supply binds

dbms_sql.bind_variable(cur_hdl,
':deptno', deptnumber); USING
deptnumber, deptname, location;
dbms_sql.bind_variable(cur_hdl,
':dname', deptname);

end;
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;

Finally, PL/SQL’s seamless integration with SQL makes it an ideal choice for native dynamic SQL
programming. For instance, in Pro*C, a variable’s data portion and null portion are separately bound
to a SQL statement [4], whereas in PL/SQL it is sufficient to bind just the variable to
the SQL statement.

PERFORMANCE

Native dynamic SQL performs significantly better than DBMS_SQL, as the PL/SQL interpreter has
native support for native dynamic SQL. The DBMS_SQL approach is based on a procedural API,
and, as a result, suffers from high procedure call and data copy overhead. For example, on every bind,
the DBMS_SQL package implementation copies the PL/SQL bind variable into its space for use

Native Dynamic SQL: A Better Alternative to DBMS_SQL 5


March 1999
during the execution phase. Similarly, on every fetch, the data is first copied into the space that the
DBMS_SQL package manages and, subsequently, the fetched data is copied, one column at a time,
into the appropriate PL/SQL variables, which results in substantial data copying overhead.

Benchmark measurements, based on Oracle8i, were performed to compare the performance of


fetching a query and executing DML operations, using native dynamic SQL and the
DBMS_SQL package.

Our first benchmark was a dynamic query loop, where a cursor is opened on a query with 1 input
bind variable and 5 select columns. The result set is fetched, one row at a time, in each iteration of
the loop and no processing is done in the loop with the fetched data. The DBMS_SQL and native
dynamic SQL sources used for the query benchmark are given in Appendix A.1.

QUERY DBMS_SQL Native Dynamic Relative


LOOP SQL Improvement
(Ultra Sparc
Instruction Counts) (Ultra Sparc (Speedup)
Instruction Counts)
1 iteration 218K 112K 1.9x

10 iterations 626K 248K 2.5x

100 iterations 5009K 1918K 2.6x

1000 45898K 15478K 2.9x


iterations

The second benchmark was an insert statement loop, where, for each iteration of the loop, one row is
dynamically inserted into a table with eight columns, with a different set of bind values each time.
The DBMS_SQL and native dynamic SQL sources used for the insert benchmark are given in
Appendix A.2.

Native Dynamic SQL: A Better Alternative to DBMS_SQL 6


March 1999
INSERT DBMS_SQL Native Dynamic Relative
LOOP SQL Improvement
(Ultra Sparc
Instruction Counts) (Ultra Sparc (Speedup)
Instruction Counts)
1 iteration 396K 125K 3.2x

10 iterations 2188K 1222K 1.8x

100 iterations 23363K 15398K 1.5x

The above benchmark results show a 1.5x-3.2x improvement in performance by using native
dynamic SQL, instead of the DBMS_SQL package.

ABILITY TO OVERCOME STATIC SQL AND DBMS_SQL LIMITATIONS

The primary use for dynamic SQL, as described earlier, is in applications that do not know the entire
structure of the SQL or PL/SQL statement they need to process, until run time. However, native
dynamic SQL can also be used in situations, as shown below, where other approaches have
certain limitations.

•= Limitations of Static SQL in PL/SQL

Currently, static SQL in PL/SQL does not support the TABLE clause. This limitation can be overcome,
using native dynamic SQL, as shown in the example below:

create type t_emp as object(id number,name varchar(20));

create type t_emplist as table of t_emp;

create table dept(id number, emps t_emplist)

nested table emps store as emp_table;

Native Dynamic SQL: A Better Alternative to DBMS_SQL 7


March 1999
declare

deptid number;

ename varchar(20);

begin

EXECUTE IMMEDIATE 'select d.id, e.name

from dept d, TABLE(d.emps) e

where e.id = 1' INTO deptid, ename;

end;

•= Limitations in the DBMS_SQL package

Native dynamic SQL can also be used for datatypes (such as objects, collections, and REFs) that are not
supported in the DBMS_SQL package.

Also, the use of %ROWTYPE variables as fetch targets is not supported in the DBMS_SQL interface. In
native dynamic SQL, similar to static SQL in PL/SQL, the resultant rows of a query can be directly fetched
into PL/SQL records.

declare

emp_rec emp%ROWTYPE;

begin

stmt_str := 'select * from emp where job = :1';

Native Dynamic SQL: A Better Alternative to DBMS_SQL 8


March 1999
-- 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;

TYPICAL USAGE OF NATIVE DYNAMIC SQL

Having described the benefits of native dynamic SQL, we now highlight some typical examples to
illustrate the power, flexibility, and ease of use of this feature. These examples show how to use
native dynamic SQL to execute DDL and DML statements, execute single- and multiple-row queries,
and invoke PL/SQL blocks.

We will use a company's HR database as our working example and make the following assumptions
about the data model:

Native Dynamic SQL: A Better Alternative to DBMS_SQL 9


March 1999
•= The list of all company locations is maintained in a master table, OFFICES. It has the following
structure:

Column NameNull? Type

LOCATION NOT_NULL VARCHAR2(200)

•= The employee information for each location is in a table, EMP_<location>. (For example, employee
information for the company's Houston office is stored in the EMP_HOUSTON table). The
employee information tables have the following structure:

Column Name Null? Type

EMPNO NOT NULL NUMBER(4)

ENAME NOT NULL VARCHAR2(10)

JOB NOT NULL VARCHAR2(9)

SAL NOT NULL NUMBER(7,2)

DEPTNO NOT NULL NUMBER(2)

Native Dynamic SQL: A Better Alternative to DBMS_SQL 10


March 1999
DDL OPERATIONS

The EXECUTE IMMEDIATE statement can be used to perform DDL operations. For example, the
following procedures can be used to add and drop an office location.

procedure add_location (loc varchar2) is

begin

-- insert new location in master table

insert into OFFICES values (loc);

-- create an employee information table

EXECUTE IMMEDIATE

'create table ' || 'EMP_' || loc ||

'( EMPNO NUMBER(4) NOT NULL,

ENAME VARCHAR2(10),

JOB VARCHAR2(9),

SAL NUMBER(7,2),

DEPTNO NUMBER(2)

Native Dynamic SQL: A Better Alternative to DBMS_SQL 11


March 1999
)';

end;

procedure drop_location (loc varchar2) is

begin

-- delete the employee table for location 'loc'

EXECUTE IMMEDIATE 'drop table ' || 'EMP_' || loc;

-- remove location from master table

delete from OFFICES where location = loc;

end;

DYNAMIC SINGLE-ROW QUERIES

The EXECUTE IMMEDIATE statement can be used to perform dynamic single-row queries. The
bind variables are specified in the USING clause, and the resultant row is fetched into the targets
specified in the INTO clause of the statement.

The following procedure retrieves the number of employees that are performing a specified job at a
particular location:

Native Dynamic SQL: A Better Alternative to DBMS_SQL 12


March 1999
function get_num_of_employees

(loc varchar2, job varchar2) return number is

……

begin

query_str := 'select count(*) from '

|| ' EMP_' || loc

|| ' where job = :job_title';

EXECUTE IMMEDIATE query_str

INTO num_of_employees

USING job;

return num_of_employees;

end;

DYNAMIC MULTIPLE-ROW QUERIES

The OPEN, FETCH, and CLOSE statements can be used to perform dynamic multi-row queries.
The example below lists all the employees with a particular job title at a specified location.

procedure list_employees(loc varchar2, job varchar2) is

type cur_typ is REF CURSOR;

Native Dynamic SQL: A Better Alternative to DBMS_SQL 13


March 1999
c cur_typ;

...

begin

query_str := 'select ename, empno from EMP_' || loc

|| ' where job = :job_title';

-- find employees who perform the specified job

OPEN c FOR query_str USING job;

loop

FETCH c INTO emp_name, emp_num;

EXIT WHEN c%NOTFOUND;

-- process row here

end loop;

CLOSE c;

end;

Native Dynamic SQL: A Better Alternative to DBMS_SQL 14


March 1999
DML OPERATIONS

The native dynamic SQL procedure shown below can be used for giving a raise to all employees with
a particular job title.

procedure salary_raise

(raise_percent number, job varchar2) is

type loc_array_type is table of varchar2(40)

index by binary_integer;

dml_str varchar2(200);

loc_array loc_array_type;

begin

-- bulk fetch the list of office locations

select location BULK COLLECT INTO loc_array

from OFFICES;

-- for each location, give a raise to employees with

-- the given 'job'

for i in loc_array.first..loc_array.last loop

Native Dynamic SQL: A Better Alternative to DBMS_SQL 15


March 1999
dml_str := 'update EMP_' || loc_array(i)

|| ' set sal = sal * (1+(:raise_percent/100))'

|| ' where job = :job_title';

EXECUTE IMMEDIATE dml_str USING raise_percent, job;

end loop;

end;

INVOKING DYNAMIC PL/SQL BLOCKS

The EXECUTE IMMEDIATE statement can also be used to invoke anonymous PL/SQL blocks. This
capability is very useful for application extension and customization, where the module to be
executed is determined dynamically at run-time.

Suppose you want to write an event dispatcher that takes an event number and dispatches to a
handler for the event that is of the form EVENT_HANDLER_<event_num>. One approach would
be to implement the dispatcher as a switch statement, as shown below, where the code handles each
event by making a static call to its appropriate handler.

procedure event_dispatcher

(event number, param number) is

begin

if (event = 1) then

EVENT_HANDLER_1(param);

Native Dynamic SQL: A Better Alternative to DBMS_SQL 16


March 1999
elsif (event = 2) then

EVENT_HANDLER_2(param);

elsif (event = 3) then

EVENT_HANDLER_3(param);

end if;

end;

The above piece of code is not very extensible, because the dispatcher code needs to be updated
whenever a handler for a new event is added. However, using native dynamic SQL you could write
an extensible event dispatcher as shown below:

procedure event_dispatcher

(event number, param number) is

begin

EXECUTE IMMEDIATE

'begin

EVENT_HANDLER_' || to_char(event) || '(:1);

end;'

USING param;

end;

Native Dynamic SQL: A Better Alternative to DBMS_SQL 17


March 1999
PERFORMANCE TIPS

The performance of PL/SQL applications that use native dynamic SQL can be significantly improved,
by utilizing some of the performance tips described below:

•= Use bind variables to improve cursor sharing

Whenever possible, use bind variables to parameterize your statement. That enables you to reuse the
associated cursor for different sets of input values.

For example, the following statement does not use bind variables. For each distinct "my_deptno," a new
cursor will be built, resulting in hard-parses and causing serious library cache contention.

EXECUTE IMMEDIATE 'DELETE FROM dept WHERE deptno = ' ||


to_char(my_deptno);

The preferred approach is to bind "my_deptno" as a bind variable, as shown below. The same cursor will be
reused for different values of the bind “my_deptno,” and, thus, it performs and scales better.

EXECUTE IMMEDIATE 'DELETE FROM dept WHERE deptno = :1' USING


my_deptno;

•= Simulate bulk SQL operations in native dynamic SQL

In Oracle8i PL/SQL, bulk bind operations are supported for processing static SQL statements. This
significantly improves the efficiency of multiple row fetches/inserts, by minimizing context switching between
PL/SQL and SQL.

Although there is no direct support for bulk operations in native dynamic SQL statements, wrapping the bulk
SQL statement in a 'BEGIN..END' block, and then executing the block, dynamically enables the PL/SQL
block to treat the inner SQL statement as static.

The example shown below can be used to copy the "ename" column of one table to another:

create type NAME_ARRAY_TYPE is

VARRAY(100) of VARCHAR2(50);

Native Dynamic SQL: A Better Alternative to DBMS_SQL 18


March 1999
procedure copy_ename_column

(table1 varchar2, table2 varchar2) is

ename_col NAME_ARRAY_TYPE;

begin

-- bulk fetch the 'ename' column into a VARRAY of

-- VARCHAR2s.

EXECUTE IMMEDIATE

'begin

select ename BULK COLLECT INTO :tab

from ' || table1 || ';

end;'

USING OUT ename_col;

-- insert the 'ename' column into another table.

EXECUTE IMMEDIATE

'begin

Native Dynamic SQL: A Better Alternative to DBMS_SQL 19


March 1999
FORALL i in :first .. :last

insert into ' || table2 || ' values (:tab(i));

end;'

USING ename_col.first, ename_col.last, ename_col;

end;

Another alternative is to fetch multiple rows in bulk, using the MULTISET and CAST operations. The
sample code shown below fetches the 'ename' column of a table (given the table's name):

procedure get_ename_column

(table_name varchar2, ename_col OUT NAME_ARRAY_TYPE) is

begin

EXECUTE IMMEDIATE

'select

CAST(MULTISET(select ename from ' ||

table_name || ')

as NAME_ARRAY_TYPE)

from dual'

INTO ename_col;

end;

Native Dynamic SQL: A Better Alternative to DBMS_SQL 20


March 1999
SUMMARY

As discussed in this paper, native dynamic SQL provides two key benefits over its current alternative,
the DBMS_SQL package, namely, performance and ease of use. Dynamic SQL applications in
PL/SQL can benefit from a 1.5x-3.2x improvement in performance, by using native dynamic SQL,
instead of the DBMS_SQL package. Also, dynamic SQL eases application development and results in
compact code that is easy to maintain and enhance. These benefits make native dynamic SQL a very
attractive solution for developing large applications, while keeping the code base compact.

Significant improvements are planned that will extend the capabilities of native dynamic SQL.
Support for bulk dynamic SQL in the future would allow users to process multiple rows of data in a
single DML statement, where the DML statement is a dynamic SQL statement. This would result in
substantial performance improvements, by minimizing context switching between SQL and PL/SQL.
Another enhancement planned is support for explicit dynamic statement management. This will
allow a dynamic statement to be executed several times with different sets of bind variables, without
incurring the statement preparation overhead for each execution. We also plan to provide a dynamic
describe capability, similar to that in the DBMS_SQL package, that will enable a developer to write
applications that need to deal with dynamic queries whose shape (i.e. structure of query columns) is
known only at run-time. These enhancements will build upon the current benefits of using native
dynamic SQL, making it an extremely powerful tool for PL/SQL application developers.

REFERENCES

1. PL/SQL User’s Guide and Reference, Oracle8i, Version 8.1, 1998.

2. Oracle8i Server Application Developer’s Guide, Version 8.1, 1998.

3. Understanding the New SQL: A Complete Guide, Jim Melton & Alan R. Simon, 1993.

4. Programmer’s Guide to the Pro*C/C++ Precompiler, Release 8.0, 1997.

5. Database Language SQL- Part 4: Persistent Stored Modules, Mar 1997, ISO Working Draft.

6. Database Language SQL- Part 5: Host language bindings, April 1997, ISO Working Draft.

Native Dynamic SQL: A Better Alternative to DBMS_SQL 21


March 1999
APPENDIX A: SOURCES USED FOR PERFORMANCE BENCHMARKS

In this section the sources used for the performance benchmarks mentioned in the section titled
“Performance” are provided.

The create table statement for the EMP table used for running the dynamic QUERY and INSERT
benchmarks is shown below.

CREATE TABLE EMP

( EMPNO NUMBER(4) NOT NULL,

ENAME VARCHAR2(10),

JOB VARCHAR2(9),

MGR NUMBER(4),

HIREDATE DATE,

SAL NUMBER(7,2),

COMM NUMBER(7,2),

DEPTNO NUMBER(2) NOT NULL);

QUERY BENCHMARK

DBMS_SQL Implementation

-- Query loop using DBMS_SQL package

create or replace procedure DBMSSQL_QUERY is

cur_hdl integer;

stmt_str varchar2(200);

rows_processed binary_integer;

enum number;

Native Dynamic SQL: A Better Alternative to DBMS_SQL 22


March 1999
name varchar2(200);

deptno number;

salary number;

hiredate date;

begin

stmt_str := 'select empno, ename, hiredate, sal, deptno

from emp

where job = :jobname';

cur_hdl := dbms_sql.open_cursor;

dbms_sql.parse(cur_hdl, stmt_str, dbms_sql.native);

-- supply binds

dbms_sql.bind_variable(cur_hdl, 'jobname', 'SALESMAN');

-- describe defines

dbms_sql.define_column(cur_hdl, 1, enum);

dbms_sql.define_column(cur_hdl, 2, name, 200);

dbms_sql.define_column(cur_hdl, 3, hiredate);

dbms_sql.define_column(cur_hdl, 4, salary);

dbms_sql.define_column(cur_hdl, 5, deptno);

-- execute cursor

Native Dynamic SQL: A Better Alternative to DBMS_SQL 23


March 1999
rows_processed := dbms_sql.execute(cur_hdl);

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, enum);

dbms_sql.column_value(cur_hdl, 2, name);

dbms_sql.column_value(cur_hdl, 3, hiredate);

dbms_sql.column_value(cur_hdl, 4, salary);

dbms_sql.column_value(cur_hdl, 5, deptno);

else

exit;

end if;

end loop;

-- close cursor

dbms_sql.close_cursor(cur_hdl);

end;

Native Dynamic SQL: A Better Alternative to DBMS_SQL 24


March 1999
Native Dynamic SQL Implementation

-- Query loop using Native Dynamic SQL package

create or replace procedure NDSQL_QUERY is

type rct is REF CURSOR;

c rct;

stmt_str varchar2(200);

enum number;

name varchar2(200);

deptno number;

salary number;

hiredate date;

begin

stmt_str := 'select empno, ename, hiredate, sal, deptno

from emp

where job = :jobname';

OPEN c FOR stmt_str USING 'SALESMAN';

loop

FETCH c INTO enum, name, hiredate, salary, deptno;

EXIT WHEN c%NOTFOUND;

end loop;

CLOSE c;

end;

Native Dynamic SQL: A Better Alternative to DBMS_SQL 25


March 1999
INSERT BENCHMARK

DBMS_SQL Implementation

-- Insert loop using DBMS_SQL package.

create or replace procedure DBMSSQL_DML

(number_of_rows binary_integer) is

cur_hdl integer;

stmt_str varchar2(200);

rows_processed binary_integer;

empno number(4);

ename varchar2(10);

job varchar2(9);

mgr number(4);

hiredate date;

sal number(7,2);

comm number(7,2);

deptno number(2);

begin

stmt_str := 'insert into emp values


(:empno,:ename,:job,:mgr,

:hiredate,:sal,:comm,:deptno)';

Native Dynamic SQL: A Better Alternative to DBMS_SQL 26


March 1999
-- open cursor

cur_hdl := dbms_sql.open_cursor;

-- parse cursor

dbms_sql.parse(cur_hdl, stmt_str, dbms_sql.native);

-- supply binds

job := 'SALESMAN';

hiredate := '17-DEC-80';

sal := 2000;

comm := 200;

deptno := 15;

for idx in 1..number_of_rows loop

empno := idx;

ename := 'EMP_' || to_char(idx);

mgr := idx;

dbms_sql.bind_variable(cur_hdl, ':empno', empno);

dbms_sql.bind_variable(cur_hdl, ':ename', ename);

dbms_sql.bind_variable(cur_hdl, ':job', job);

dbms_sql.bind_variable(cur_hdl, ':mgr', mgr);

dbms_sql.bind_variable(cur_hdl, ':hiredate', hiredate);

dbms_sql.bind_variable(cur_hdl, ':sal', sal);

Native Dynamic SQL: A Better Alternative to DBMS_SQL 27


March 1999
dbms_sql.bind_variable(cur_hdl, ':comm', comm);

dbms_sql.bind_variable(cur_hdl, ':deptno', deptno);

-- execute cursor

rows_processed := dbms_sql.execute(cur_hdl);

end loop;

-- close cursor

dbms_sql.close_cursor(cur_hdl);

end;

Native Dynamic SQL Implementation

-- Insert loop using Native Dynamic SQL package

create or replace procedure NDSQL_DML

(number_of_rows binary_integer) is

stmt_str varchar2(200);

empno number(4);

ename varchar2(10);

job varchar2(9);

mgr number(4);

hiredate date;

sal number(7,2);

comm number(7,2);

deptno number(2);

Native Dynamic SQL: A Better Alternative to DBMS_SQL 28


March 1999
begin

stmt_str := 'insert into emp values


(:1,:2,:3,:4,:5,:6,:7,:8)';

-- supply binds

job := 'SALESMAN';

hiredate := '17-DEC-80';

sal := 2000;

comm := 200;

deptno := 15;

for idx in 1..number_of_rows loop

empno := idx;

ename := 'EMP_' || to_char(idx);

mgr := idx;

EXECUTE IMMEDIATE stmt_str

USING empno, ename, job, mgr, hiredate, sal, comm,


deptno;

end loop;

end;

Native Dynamic SQL: A Better Alternative to DBMS_SQL 29


March 1999
Oracle Corporation
World Headquarters
500 Oracle Parkway
Redwood Shores, CA 94065
U.S.A.

Worldwide Inquiries:
+1.650.506.7000
Fax +1.650.506.7200
http://www.oracle.com/

Copyright © Oracle Corporation 1999


All Rights Reserved

This document is provided for informational purposes only, and


the information herein is subject to change without notice.
Please report any errors herein to Oracle Corporation. Oracle
Corporation does not provide any warranties covering and
specifically disclaims any liability in connection with this
document.

Oracle is a registered trademark, and Oracle8i, Oracle8, PL/SQL,


and Oracle Expert are trademarks or registered trademarks of
Oracle Corporation. All other company and product names
mentioned are used for identification purposes only and may be
trademarks of their respective owners.