Native Dynamic SQL
Hello friends,
I am again come with new tutorial, Native Dynamic SQL. In this tutorial we will learn –
1) What is Native Dynamic SQL
2) How it can be used in PL/SQL
3) Benefits of the Native Dynamic SQL.
What is Native Dynamic SQL?
Native dynamic SQL is the mechanism where you can dynamically perform the operation on the oracle database schemas. Native dynamic SQL makes your program more flexible in such situations where you don’t know any information about what to do, in advance. Consider the situation where a reporting tool maintain data on daily basis and there are a lot of source table which contain the data on the basis of some parameters and these parameters can also be changed at run time. So what you will do in this situation. Native Dynamic SQL can be used to handle this type of situation.
Native Dynamic SQL statement can be built same as a string variable. And also the bind variables can be used with them to improve the performance of the operations. Remember when you perform any of the operation with PL/SQL, PL/SQL automatically convert the variables of the statement to the bind variable to improve the performance of the statement. When you build up such statements with the Native Dynamic SQL then you have to specify the bind variables with the statement, however it is not mandatory. If you will not give the bind variable, PL/SQL will automatically convert them into bind variables but it will give more overhead on the Server.
So, The Native Dynamic SQL statements can be generated at the run time (dynamically).
How it can be used in PL/SQL
Native Dynamic SQL statements can be executed by using EXECUTE IMMEDIATE statement following by the single quoted varchar variable with SQL statement.
DECLARE
str VARCHAR2 (4000);
BEGIN
str:= ‘DELETE FROM STUDENT_MASTER WHERE STUDENT_ID=1′;
EXECUTE IMMEDIATE str;
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
Above example just delete the student with student id =1.
You can also use bind variable with the Native Dynamic SQL for improving the performance of the direct SQL statements.
Benefits of the Native Dynamic SQL
1) You can use DDL (CREATE TABLE, DROP TABLE, ALTER TABLE etc) statements and DCL Statements with the PL/SQL block. In PL/SQL these statement can’t be executed statically.
2) By using Native Dynamic SQL statements you can create the SQL statements with using different WHERE clause conditions in a SELECT statement.
EXECUTE IMMEDIATE The Magic statement to execute Dynamic SQL
EXECUTE IMMEDIATE is the statement for executing the SQL statements dynamically in the PL/SQL block or even for executing the PL/SQL block itself.
Syntax of Execute immediate -
EXECUTE IMMEDIATE dynamic_string
[INTO {define_variable[, define_variable]… | record}]
[USING [IN | OUT | IN OUT] bind_argument
[, [IN | OUT | IN OUT] bind_argument]…]
[{RETURNING | RETURN} INTO bind_argument[, bind_argument]…];
Brief Explanation –
EXECUTE IMMEDIATE is used to dynamically execute the SQL statement where dynamic_string is the string type variable which contains the Dynamic SQL. INTO clause is used to take the selected values form the query into the defined variables and record is the %ROWTYPE or user defined records. USING clause is used to take IN or OUT bind variables. RETURNING INTO clause is used with the DML statements which have the RETURNING clause with them for returning the affected column value.
Consider the following example –
CREATE OR REPLACE procedure WEALTHMAKER.MyTest as
sql1 varchar(4000);
myrefcur sys_refcursor;
employeecodex number;
employeenamex varchar2(20);
salarymonthx varchar2(20);
salaryyearx varchar2(20);
salaryx varchar2(20);
salaryy number;
TYPE RefEmpTyp IS REF CURSOR;
cv RefEmpTyp;
begin
/***************************************************************************************
BLOCK1 - DCL STATEMENT
***************************************************************************************/
– Droping table if exists
begin
execute immediate ‘drop table MyEmployeeMaster’;
exception
when others then
null;
end;
– Droping table if exists
begin
execute immediate ‘drop table MyEmployeeSalary’;
exception
when others then
null;
end;
– Droping view if exists
begin
execute immediate ‘drop view MyClientView’;
exception
when others then
null;
end;
– Creating a master table
begin
execute immediate ‘create table MyEmployeeMaster(EmployeeId number,EmployeeName varchar2(20))’;
exception
when others then
null;
end;
– Creating Detailed Table
begin
execute immediate ‘create table MyEmployeeSalary(EmployeeId number,Salary varchar2(20),SalaryMonth number,SalaryYear number)’;
exception
when others then
null;
end;
/******************************************************************************************
BLOCK2 - DML STATEMENT
******************************************************************************************/
– Inserting values in Master Table
execute immediate ‘insert into MyEmployeeMaster values (1,”Vinay Hatwal”)’;
execute immediate ‘insert into MyEmployeeMaster values (2,”Piyush Aggrawal”)’;
execute immediate ‘insert into MyEmployeeMaster values (3,”Vinita Sharma”)’;
execute immediate ‘insert into MyEmployeeMaster values (4,”Varsha Dhiman”)’;
execute immediate ‘insert into MyEmployeeMaster values (5,”Pawan Kumar”)’;
– Inserting Values in Detailed Table
execute immediate ‘insert into MyEmployeeSalary values (1,2000,2,2008)’;
execute immediate ‘insert into MyEmployeeSalary values (1,2000,3,2008)’;
execute immediate ‘insert into MyEmployeeSalary values (1,2000,4,2008)’;
execute immediate ‘insert into MyEmployeeSalary values (1,2000,5,2008)’;
execute immediate ‘insert into MyEmployeeSalary values (2,2000,2,2008)’;
execute immediate ‘insert into MyEmployeeSalary values (2,2000,3,2008)’;
execute immediate ‘insert into MyEmployeeSalary values (2,2000,4,2008)’;
execute immediate ‘insert into MyEmployeeSalary values (2,2000,5,2008)’;
execute immediate ‘insert into MyEmployeeSalary values (3,2000,2,2008)’;
execute immediate ‘insert into MyEmployeeSalary values (3,2000,4,2008)’;
commit;
/******************************************************************************************
BLOCK3 - QUERY
******************************************************************************************/
– Creating View for Displaying
SQL1:= ‘ create or replace view MyClientView as ‘;
SQL1:= SQL1 || ’select m.EmployeeId,m.EmployeeName,s.SALARYMONTH,s.SALARYYEAR,s.SALARY from MyEmployeeSalary s, MyEmployeeMaster m ‘;
SQL1:= SQL1 || ‘where s.EmployeeId(+)=m.EmployeeId and (s.salarymonth=”02” or s.salarymonth is null) ‘;
execute immediate sql1;
open cv for ’select * from MyClientView’;
loop
fetch cv into employeecodex,employeenamex,salarymonthx,salaryyearx,salaryx;
EXIT WHEN cv%NOTFOUND;
dbms_output.PUT_line(employeecodex || ‘ ‘ || employeenamex || ‘ ‘ || salarymonthx || ‘ ‘ || salaryyearx || ‘ ‘ || salaryx);
end loop;
/******************************************************************************************
BLOCK4 - DML STATEMENT WITH RETURNING INTO VLAUSE
******************************************************************************************/
execute immediate ‘update MyEmployeeSalary set salary=50000 where employeeid=1 and salarymonth=2 and salaryyear=2008 returning salary into :2′ returning into salaryy;
commit;
dbms_output.PUT_line(”);
dbms_output.PUT_line(”);
dbms_output.PUT_line(‘Updated Salary—-’ || salaryy);
open cv for ’select * from MyClientView’;
loop
fetch cv into employeecodex,employeenamex,salarymonthx,salaryyearx,salaryx;
EXIT WHEN cv%NOTFOUND;
dbms_output.PUT_line(employeecodex || ‘ ‘ || employeenamex || ‘ ‘ || salarymonthx || ‘ ‘ || salaryyearx || ‘ ‘ || salaryx);
end loop;
exception
when others then
dbms_output.put_line(SQLERRM(SQLCODE));
end;
Brief Explanation –
BLOCK 1 – Specifies the DDL statement, some Tables are dropped and Some Tables are created with using the dynamic SQL.
BLOCK 2 – Specifies some DML statements which insert values into the table created in the BLOCK 1.
BLOCK 3 – View is created to show the data at the run time by using the Implicit Cursor for the Query.
BLOCK 4 – Specifies DML statement UPDATE to show the working of RETURNING INTO clause with the EXECUTE IMMEDIATE.
USING Vs. RETURNING INTO
By using OUT parameter with USING clause you can also take the advantage of the RETURNING INTO clause.
Consider the following block of code –
CREATE OR REPLACE procedure WEALTHMAKER.UsingVsRETINTO as
str varchar2(4000);
bsalary number;
bsalary_out number;
bemployeeid number;
bmonth number;
byear number;
begin
bsalary:=40000;
bemployeeid:=1;
bmonth:=2;
byear:=2008;
str:= ‘ update myemployeesalary set salary=:bind_salary where employeeid=:bind_employeeid ‘;
str:= str || ‘ and salarymonth=:bind_month and salaryyear=:bind_year returning salary into :bindsalaryret ‘;
–Statement 1
execute immediate str using bsalary,bemployeeid,bmonth,byear,out bsalary_out;
dbms_output.put_line(bsalary_out);
bsalary:=50000;
–Statement 1
execute immediate str using bsalary,bemployeeid,bmonth,byear returning into bsalary_out;
dbms_output.put_line(bsalary_out);
exception
when others then
dbms_output.put_line(SQLERRM(SQLCODE));
end;
In the above example you can see in Statement 1, the updated salary is taken out into bsalary_out OUT parameter by using the USING clause
But in the case of Statement 2, updated salary is taken out by using the RETURNING INTO clause.
So, finally you can use any of the statement to return the result of the DML statement.
The only difference in these two statements is, with USING clause all the followed parameter are IN mode by default, it means you need not to specify the IN mode for the variable, On the other hand in the case of RETURNING INTO clause all the variables are in the OUT mode by default.
Using Schema Name with Dynamic SQL
Suppose you want to user the Scheme name with the Dynamic SQL then normally you might write the code like the following –
CREATE PROCEDURE drop_some_table (tablename IN VARCHAR2) AS
BEGIN
EXECUTE IMMEDIATE ‘DROP TABLE :tab’ USING table_name;
END;
But Remember, you will find the error Invalid Table Name because you can’t use bind variables with any schema name. So you should write the following code to debug the above code.
CREATE PROCEDURE drop_some_table (tablename IN VARCHAR2) AS
BEGIN
EXECUTE IMMEDIATE ‘DROP TABLE ‘ || table_name;
END;
Duplicate Placeholders
Placeholders in Dynamic SQL are the elements by which the bind variables are associated with the corresponding item followed by the USING clause. These variables are associated with the values by the position not by the name. So remember the you can use the same name with the placeholders. For examples consider the following line of code:
sql_stmt := ’INSERT INTO payroll VALUES (:x,
, :y,
)’;
it does not matter you are writing the execute stament like this
EXECUTE IMMEDIATE sql_stmt USING a, a, b, a;
Or
EXECUTE IMMEDIATE sql_stmt USING a, b, b, a;
Hi,
Great to see this article.It really helped a lot.I wish if you write something related to global environment today so that it could help the freshes like us.
Comment by saket — July 16, 2009 @ 6:02 am |