Native Dynamic SQL
Native dynamic SQL processes most dynamic SQL statements with the EXECUTE
IMMEDIATE
statement.
If the dynamic SQL statement is a SELECT
statement that returns multiple rows, native dynamic SQL gives you these choices:
-
Use the
EXECUTE
IMMEDIATE
statement with theBULK
COLLECT
INTO
clause. -
Use the
OPEN
FOR
,FETCH
, andCLOSE
statements.
The SQL cursor attributes work the same way after native dynamic SQL INSERT
, UPDATE
, DELETE
, MERGE
, and single-row SELECT
statements as they do for their static SQL counterparts. For more information about SQL cursor attributes, see "Cursors Overview".
Topics
EXECUTE IMMEDIATE Statement
The EXECUTE
IMMEDIATE
statement is the means by which native dynamic SQL processes most dynamic SQL statements.
If the dynamic SQL statement is self-contained (that is, if it has no placeholders for bind variables and the only result that it can possibly return is an error), then the EXECUTE
IMMEDIATE
statement needs no clauses.
If the dynamic SQL statement includes placeholders for bind variables, each placeholder must have a corresponding bind variable in the appropriate clause of the EXECUTE
IMMEDIATE
statement, as follows:
-
If the dynamic SQL statement is a
SELECT
statement that can return at most one row, put out-bind variables (defines) in theINTO
clause and in-bind variables in theUSING
clause. -
If the dynamic SQL statement is a
SELECT
statement that can return multiple rows, put out-bind variables (defines) in theBULK
COLLECT
INTO
clause and in-bind variables in theUSING
clause. -
If the dynamic SQL statement is a DML statement without a
RETURNING
INTO
clause, other thanSELECT
, put all bind variables in theUSING
clause. -
If the dynamic SQL statement is a DML statement with a
RETURNING
INTO
clause, put in-bind variables in theUSING
clause and out-bind variables in theRETURNING
INTO
clause. -
If the dynamic SQL statement is an anonymous PL/SQL block or a
CALL
statement, put all bind variables in theUSING
clause.If the dynamic SQL statement invokes a subprogram, ensure that:
-
The subprogram is either created at schema level or declared and defined in a package specification.
-
Every bind variable that corresponds to a placeholder for a subprogram parameter has the same parameter mode as that subprogram parameter and a data type that is compatible with that of the subprogram parameter.
-
No bind variable is the reserved word
NULL
.To work around this restriction, use an uninitialized variable where you want to use
NULL
, as in Example 8-7. -
No bind variable has a data type that SQL does not support (such as associative array indexed by string).
If the data type is a collection or record type, then it must be declared in a package specification.
-
Note:
Bind variables can be evaluated in any order. If a program determines order of evaluation, then at the point where the program does so, its behavior is undefined.
In Example 8-4, Example 8-5, and Example 8-6, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a subprogram that has a formal parameter of a PL/SQL collection type. Collection types are not SQL data types. In each example, the collection type is declared in a package specification, and the subprogram is declared in the package specification and defined in the package body.
See Also:
-
"CREATE FUNCTION Statement" for information about creating functions at schema level
-
"CREATE PROCEDURE Statement" for information about creating procedures at schema level
-
"PL/SQL Packages" for information about packages
-
"CREATE PACKAGE Statement" for information about declaring subprograms in packages
-
"CREATE PACKAGE BODY Statement" for information about declaring and defining subprograms in packages
-
"CREATE PACKAGE Statement" for more information about declaring types in a package specification
-
"EXECUTE IMMEDIATE Statement"for syntax details of the
EXECUTE
IMMEDIATE
statement -
"PL/SQL Collections and Records" for information about collection types
Example 8-1 Invoking Subprogram from Dynamic PL/SQL Block
In this example, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a subprogram created at schema level.
-- Subprogram that dynamic PL/SQL block invokes:
CREATE OR REPLACE PROCEDURE create_dept (
deptid IN OUT NUMBER,
dname IN VARCHAR2,
mgrid IN NUMBER,
locid IN NUMBER
) AUTHID DEFINER AS
BEGIN
deptid := departments_seq.NEXTVAL;
INSERT INTO departments (
department_id,
department_name,
manager_id,
location_id
)
VALUES (deptid, dname, mgrid, locid);
END;
/
DECLARE
plsql_block VARCHAR2(500);
new_deptid NUMBER(4);
new_dname VARCHAR2(30) := 'Advertising';
new_mgrid NUMBER(6) := 200;
new_locid NUMBER(4) := 1700;
BEGIN
-- Dynamic PL/SQL block invokes subprogram:
plsql_block := 'BEGIN create_dept(:a, :b, :c, :d); END;';
/* Specify bind variables in USING clause.
Specify mode for first parameter.
Modes of other parameters are correct by default. */
EXECUTE IMMEDIATE plsql_block
USING IN OUT new_deptid, new_dname, new_mgrid, new_locid;
END;
/
Example 8-2 Dynamically Invoking Subprogram with BOOLEAN Formal Parameter
In this example, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a
subprogram that has a formal parameter of the PL/SQL data type BOOLEAN
.
CREATE OR REPLACE PROCEDURE p (x BOOLEAN) AUTHID DEFINER AS
BEGIN
IF x THEN
DBMS_OUTPUT.PUT_LINE('x is true');
END IF;
END;
/
DECLARE
dyn_stmt VARCHAR2(200);
b BOOLEAN := TRUE;
BEGIN
dyn_stmt := 'BEGIN p(:x); END;';
EXECUTE IMMEDIATE dyn_stmt USING b;
END;
/
Result:
x is true
Example 8-3 Dynamically Invoking Subprogram with RECORD Formal Parameter
In this example, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a subprogram that has a formal parameter of the PL/SQL (but not SQL) data type RECORD
. The record type is declared in a package specification, and the subprogram is declared in the package specification and defined in the package body.
CREATE OR REPLACE PACKAGE pkg AUTHID DEFINER AS
TYPE rec IS RECORD (n1 NUMBER, n2 NUMBER);
PROCEDURE p (x OUT rec, y NUMBER, z NUMBER);
END pkg;
/
CREATE OR REPLACE PACKAGE BODY pkg AS
PROCEDURE p (x OUT rec, y NUMBER, z NUMBER) AS
BEGIN
x.n1 := y;
x.n2 := z;
END p;
END pkg;
/
DECLARE
r pkg.rec;
dyn_str VARCHAR2(3000);
BEGIN
dyn_str := 'BEGIN pkg.p(:x, 6, 8); END;';
EXECUTE IMMEDIATE dyn_str USING OUT r;
DBMS_OUTPUT.PUT_LINE('r.n1 = ' || r.n1);
DBMS_OUTPUT.PUT_LINE('r.n2 = ' || r.n2);
END;
/
Result:
r.n1 = 6
r.n2 = 8
Example 8-4 Dynamically Invoking Subprogram with Assoc. Array Formal Parameter
In this example, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a subprogram that has a formal parameter of the PL/SQL collection type associative array indexed by PLS_INTEGER
.
Note:
An associative array type used in this context must be indexed by PLS_INTEGER
.
CREATE OR REPLACE PACKAGE pkg AUTHID DEFINER AS
TYPE number_names IS TABLE OF VARCHAR2(5)
INDEX BY PLS_INTEGER;
PROCEDURE print_number_names (x number_names);
END pkg;
/
CREATE OR REPLACE PACKAGE BODY pkg AS
PROCEDURE print_number_names (x number_names) IS
BEGIN
FOR i IN x.FIRST .. x.LAST LOOP
DBMS_OUTPUT.PUT_LINE(x(i));
END LOOP;
END;
END pkg;
/
DECLARE
digit_names pkg.number_names;
dyn_stmt VARCHAR2(3000);
BEGIN
digit_names(0) := 'zero';
digit_names(1) := 'one';
digit_names(2) := 'two';
digit_names(3) := 'three';
digit_names(4) := 'four';
digit_names(5) := 'five';
digit_names(6) := 'six';
digit_names(7) := 'seven';
digit_names(8) := 'eight';
digit_names(9) := 'nine';
dyn_stmt := 'BEGIN pkg.print_number_names(:x); END;';
EXECUTE IMMEDIATE dyn_stmt USING digit_names;
END;
/
Result:
zero
one
two
...
nine
Example 8-5 Dynamically Invoking Subprogram with Nested Table Formal Parameter
In this example, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a subprogram that has a formal parameter of the PL/SQL collection type nested table.
CREATE OR REPLACE PACKAGE pkg AUTHID DEFINER AS
TYPE names IS TABLE OF VARCHAR2(10);
PROCEDURE print_names (x names);
END pkg;
/
CREATE OR REPLACE PACKAGE BODY pkg AS
PROCEDURE print_names (x names) IS
BEGIN
FOR i IN x.FIRST .. x.LAST LOOP
DBMS_OUTPUT.PUT_LINE(x(i));
END LOOP;
END;
END pkg;
/
DECLARE
fruits pkg.names;
dyn_stmt VARCHAR2(3000);
BEGIN
fruits := pkg.names('apple', 'banana', 'cherry');
dyn_stmt := 'BEGIN pkg.print_names(:x); END;';
EXECUTE IMMEDIATE dyn_stmt USING fruits;
END;
/
Result:
apple
banana
cherry
Example 8-6 Dynamically Invoking Subprogram with Varray Formal Parameter
In this example, the dynamic PL/SQL block is an anonymous PL/SQL block that invokes a subprogram that has a formal parameter of the PL/SQL collection type varray.
CREATE OR REPLACE PACKAGE pkg AUTHID DEFINER AS
TYPE foursome IS VARRAY(4) OF VARCHAR2(5);
PROCEDURE print_foursome (x foursome);
END pkg;
/
CREATE OR REPLACE PACKAGE BODY pkg AS
PROCEDURE print_foursome (x foursome) IS
BEGIN
IF x.COUNT = 0 THEN
DBMS_OUTPUT.PUT_LINE('Empty');
ELSE
FOR i IN x.FIRST .. x.LAST LOOP
DBMS_OUTPUT.PUT_LINE(x(i));
END LOOP;
END IF;
END;
END pkg;
/
DECLARE
directions pkg.foursome;
dyn_stmt VARCHAR2(3000);
BEGIN
directions := pkg.foursome('north', 'south', 'east', 'west');
dyn_stmt := 'BEGIN pkg.print_foursome(:x); END;';
EXECUTE IMMEDIATE dyn_stmt USING directions;
END;
/
Result:
north
south
east
west
Example 8-7 Uninitialized Variable Represents NULL in USING Clause
This example uses an uninitialized variable to represent the reserved word NULL
in the USING
clause.
CREATE TABLE employees_temp AS SELECT * FROM EMPLOYEES;
DECLARE
a_null CHAR(1); -- Set to NULL automatically at run time
BEGIN
EXECUTE IMMEDIATE 'UPDATE employees_temp SET commission_pct = :x'
USING a_null;
END;
/
OPEN FOR, FETCH, and CLOSE Statements
If the dynamic SQL statement represents a SELECT
statement that returns multiple rows, you can process it with native dynamic SQL as follows:
-
Use an
OPEN
FOR
statement to associate a cursor variable with the dynamic SQL statement. In theUSING
clause of theOPEN
FOR
statement, specify a bind variable for each placeholder in the dynamic SQL statement.The
USING
clause cannot contain the literalNULL
. To work around this restriction, use an uninitialized variable where you want to useNULL
, as in Example 8-7. -
Use the
FETCH
statement to retrieve result set rows one at a time, several at a time, or all at once. -
Use the
CLOSE
statement to close the cursor variable.
The dynamic SQL statement can query a collection if the collection meets the criteria in "Querying a Collection".
See Also:
-
"OPEN FOR Statement" for syntax details
-
"FETCH Statement" for syntax details
-
"CLOSE Statement" for syntax details
Example 8-8 Native Dynamic SQL with OPEN FOR, FETCH, and CLOSE Statements
This example lists all employees who are managers, retrieving result set rows one at a time.
DECLARE
TYPE EmpCurTyp IS REF CURSOR;
v_emp_cursor EmpCurTyp;
emp_record employees%ROWTYPE;
v_stmt_str VARCHAR2(200);
v_e_job employees.job_id%TYPE;
BEGIN
-- Dynamic SQL statement with placeholder:
v_stmt_str := 'SELECT * FROM employees WHERE job_id = :j';
-- Open cursor & specify bind variable in USING clause:
OPEN v_emp_cursor FOR v_stmt_str USING 'MANAGER';
-- Fetch rows from result set one at a time:
LOOP
FETCH v_emp_cursor INTO emp_record;
EXIT WHEN v_emp_cursor%NOTFOUND;
END LOOP;
-- Close cursor:
CLOSE v_emp_cursor;
END;
/
Example 8-9 Querying a Collection with Native Dynamic SQL
This example is like Example 7-30 except that the collection variable v1
is a bind variable.
CREATE OR REPLACE PACKAGE pkg AUTHID DEFINER AS TYPE rec IS RECORD(f1 NUMBER, f2 VARCHAR2(30)); TYPE mytab IS TABLE OF rec INDEX BY pls_integer; END; / DECLARE v1 pkg.mytab; -- collection of records v2 pkg.rec; c1 SYS_REFCURSOR; BEGIN OPEN c1 FOR 'SELECT * FROM TABLE(:1)' USING v1; FETCH c1 INTO v2; CLOSE c1; DBMS_OUTPUT.PUT_LINE('Values in record are ' || v2.f1 || ' and ' || v2.f2); END; /
Repeated Placeholder Names in Dynamic SQL Statements
If you repeat placeholder names in dynamic SQL statements, be aware that the way placeholders are associated with bind variables depends on the kind of dynamic SQL statement.
Topics
Dynamic SQL Statement is Not Anonymous Block or CALL Statement
If the dynamic SQL statement does not represent an anonymous PL/SQL block or a CALL
statement, repetition of placeholder names is insignificant.
Placeholders are associated with bind variables in the USING
clause by position, not by name.
For example, in this dynamic SQL statement, the repetition of the name :x
is insignificant:
sql_stmt := 'INSERT INTO payroll VALUES (:x, :x, :y, :x)';
In the corresponding USING
clause, you must supply four bind variables. They can be different; for example:
EXECUTE IMMEDIATE sql_stmt USING a, b, c, d;
The preceding EXECUTE
IMMEDIATE
statement runs this SQL statement:
INSERT INTO payroll VALUES (a, b, c, d)
To associate the same bind variable with each occurrence of :x
, you must repeat that bind variable; for example:
EXECUTE IMMEDIATE sql_stmt USING a, a, b, a;
The preceding EXECUTE
IMMEDIATE
statement runs this SQL statement:
INSERT INTO payroll VALUES (a, a, b, a)
Dynamic SQL Statement is Anonymous Block or CALL Statement
If the dynamic SQL statement represents an anonymous PL/SQL block or a CALL
statement, repetition of placeholder names is significant.
Each unique placeholder name must have a corresponding bind variable in the USING
clause. If you repeat a placeholder name, you need not repeat its corresponding bind variable. All references to that placeholder name correspond to one bind variable in the USING
clause.
Example 8-10 Repeated Placeholder Names in Dynamic PL/SQL Block
In this example, all references to the first unique placeholder name,
:x
, are associated with the first bind variable in the
USING
clause, a
, and the second unique placeholder name,
:y
, is associated with the second bind variable in the
USING
clause, b
.
CREATE PROCEDURE calc_stats (
w NUMBER,
x NUMBER,
y NUMBER,
z NUMBER )
IS
BEGIN
DBMS_OUTPUT.PUT_LINE(w + x + y + z);
END;
/
DECLARE
a NUMBER := 4;
b NUMBER := 7;
plsql_block VARCHAR2(100);
BEGIN
plsql_block := 'BEGIN calc_stats(:x, :x, :y, :x); END;';
EXECUTE IMMEDIATE plsql_block USING a, b; -- calc_stats(a, a, b, a)
END;
/
Result:
19