PLSQL
PLSQL
Structure of PL/SQL
u Standard PL/SQL code segment is called a Block
u A block consists of three parts or sections
– Declaration Part
– Executable Part
– Exception Handling Part
DECLARE
Declarations
BEGIN
Executable Statements
EXCEPTION
Exception Handlers
END;
u Declaration Part
– optional part where variables are defined
u Executable Part
– mandatory part which consists of executable statements
u Exception Handling Part
– optional part which consists of code for handling errors (runtime)
Pl/SQL Files -à
Ø PL/SQL programs can be written in any editor and saved as files with .sql extension
Ø Can also use “ED” command in SQL*Plus to create a PL/SQL program file
Ø Use the “@ <filename>” command to execute a PL/SQL program file
o Variables --
Ø Used to store results of a query for later processing, or to calculate values to be
inserted into database tables
Ø Can be used anywhere in an expression, either in SQL or PL/SQL statements
Ø Must be declared before referencing it in other statements, including other
declarative statements
Ø Are declared by specifying the name along with the datatype
Ø Can be declared to be of any datatype native to Oracle
Ø Examples
oldfare NUMBER(5);
m_name VARCHAR(15);
(Note – Set Serveroutput On has to be given when a session starts for displaying
the output statements_)
declare
x number;
begin
x := 67;
dbms_output.put_line(x);
dbms_output.put_line('The value of x is '|| x);
end;
Declaring variable in declare block.
Assigning value in in begin block using := .
Output statement is dbms_output.put_line
Concatenation operator is ||
Command terminator is ; after end
declare
z number;
a varchar2(10);
begin
z := &z;
a := '&a';
dbms_output.put_line('Z is '|| z);
dbms_output.put_line('A is '|| a);
end;
-------------------------------------------------------------------------------
declare
r CONSTANT number :=100;
begin
/* r := r + 100; Not possible*/
dbms_output.put_line(r);
end;
% Type Attribute –
u Provides datatype of a variable or column
u Useful when declaring a variable that refers to a column in a database
– exact datatype of column need not be known
– if column definition changes, variable datatype changes accordingly
at runtime
u Example
oldfare fare.first_fare%TYPE;
newfare oldfare%TYPE;
declare
a emp.ename%type;
b emp.sal%type;
c emp.deptno%type;
/*Using %TYPE attribute for variable data type*/
begin
select ename,sal,deptno
into a,b,c
from emp
where ename = 'KING';
dbms_output.put_line(a ||'-'|| b ||'-' || c);
end;
%RowType Attribute –
u Useful when declaring a record variable having same structure as a row in a
table or view, or as a row fetched from a cursor
u Fields in the record have same names and datatypes as the columns in the
table/view
u Example
emp_rec employee%ROWTYPE;
u A specific field can be referenced using
emp_rec.emp_num;
declare
E emp%rowtype;
/*rowtype attribute holds the datatype of the columns of the
entire row*/
begin
select ename,sal,deptno INTO E.ename,E.sal,E.deptno
from emp
where ename = 'MARTIN';
dbms_output.put_line(E.sal);
dbms_output.put_line(E.ename);
dbms_output.put_line(e.deptno);
end;
Conditional Statements – IF
u The selection structure tests a condition, then executes one sequence of statements
instead of another, depending on the condition
u There are three forms of statements
– IF-THEN
– IF-THEN-ELSE
– IF-THEN-ELSIF
u Sequence of statements is executed only if the condition evaluates to TRUE
u If condition evaluates to FALSE or NULL, it does nothing
u In either case control passes to next statement after the IF-THEN structure
IF <condition> THEN
statements;
END IF;
u Sequence of statements in the ELSE clause is executed only if the condition
evaluates to FALSE or NULL
IF <condition> THEN
statements;
ELSE
statements;
END IF;
--------------------------------------------------------------------------------
declare
/*Simple if condition */
x number;
begin
x := &x;
if x >= 35 then
dbms_output.put_line('Passed');
else
dbms_output.put_line('Failed');
end if;
end;
-----------------------------------------------------
IF-THEN-ELSIF Structure
u This construct allows selection of action from several mutually exclusive alternatives
u The IF statement can have any number of ELSIF clauses
u The final ELSE is optional
u Conditions are evaluated one by one from top to bottom
Syntax
IF <condition1> THEN
statements;
ELSIF <condition2> THEN
statements;
ELSIF <condition3> THEN
statements;
ELSE
statements;
END IF;
Example 1 –
Declare
y number;
/*Multiple ifs */
Begin
y := &y;
if y >= 70 then
dbms_output.put_line('Distinction');
elsif y >= 60 then
dbms_output.put_line('First class');
elsif y >= 50 then
dbms_output.put_line('Second class');
elsif y >= 35 then
dbms_output.put_line('Passed');
else
dbms_output.put_line('Failed');
end if;
end;
Example 2
create table adm
(Name varchar2(30),
Marks number(3),
College varchar2(30),
Fees number(5));
Declare
n adm.name%type;
m adm.marks%type;
c adm.college%type;
f adm.fees%type;
Begin
n := '&n';
m := &m;
if m >= 95 then
c := 'COEP';
f := 10000;
elsif m >= 90 then
c := 'MIT';
f := 15000;
elsif m >= 85 then
c := 'VIT';
f := 22000;
elsif m >= 80 then
c := 'D Y Patil';
f := 27000;
elsif m >= 75 then
c := 'Pune Vidyarthi';
f := 33000;
else
dbms_output.put_line('Cannot get admission');
end if;
end;
=========================================================
===========================================
LOOPS
u The ability to repeat or skip sections of a block can be achieved with the usage of
LOOP or GOTO statements
u There are three forms of the LOOP statement
– LOOP
– WHILE-LOOP
– FOR-LOOP
LOOP Statement
u LOOP repeats a sequence of statements
u Statements to be repeated are placed between keyword LOOP and END LOOP
u With each iteration of the loop, the sequence of statements is executed, then control
resumes at the top of the loop
LOOP
statements;
END LOOP;
EXIT Statement
u Used to complete a loop if further processing in a loop is undesirable or impossible
u There are two forms of the EXIT statement
– EXIT
– EXIT-WHEN
u Forces a loop to complete unconditionally
u Must be placed inside a loop
LOOP
statements;
IF <condition> THEN
EXIT; -- exit loop immediately
END IF;
END LOOP;
-- control resumes here
Example of Loop –
/*To show 1 to 10 on screen*/
Declare
x number;
Begin
x := 1;
Loop
dbms_output.put_line(x);
x := x + 1;
exit when x > 10;
End Loop;
End;
Declare
x number;
Begin
x := 5;
Loop
Insert into five
values(x);
x := x + 5;
exit when x > 50;
End Loop;
End;
FOR LOOP
Advantages --
1) No need of declaring loop variable
2) No need of giving condition
3) No need of updation statement (increment or decrement )
4)Code becomes small and compact
Disadvantage --
Updation can be done by only one.
Syntax –
FOR <counter> IN [REVERSE]
lower_bound .. higher_bound LOOP
statements;
END LOOP
begin
for x in 1..10
Loop
dbms_output.put_line(x);
End Loop;
end;
Example 2
/*Reverse for loop 10,9,8 … 1*/
Begin
for i in REVERSE 1 ..10
Loop
dbms_output.put_line(i);
End Loop;
end;
Example 3 –
Calculating compound interest for a principal of Rs.100 @10% for each year.
Values will be shown of the CI after each year.
create table CI_100
(year number(2),
total number(4));
----------------------------------
Declare
p number := 100;
tot number;
/*Calculation of compound interest.
Rs.100 is principal.
Rate of interest is 10%.
Period is 5 years.
*/
Begin
for y in 1..5
Loop
/* Tot variable is getting 10% more than p */
tot := p + p * 0.10;
Insert into CI_100
values(y,tot);
/*Since the next interest is based on the current interest
so the tot will be considered as p for the next year*/
p := tot;
End Loop;
end;
WHILE-LOOP Statement
declare
x number;
Begin
x := 1;
while x <=15
Loop
dbms_output.put_line(x);
x := x + 1;
End Loop;
end;
==============================CURSORS=================
=======================
Example 1
To transfer names and sal of employees from emp table where sal >= 3500 in
table try1
create table try1
(no number,
ename varchar2(50),
sal number);
Declare
Cursor cf is
select ename,sal
from emp
where sal >= 3500;
M cf%rowtype;
N number;
Begin
Open cf;
N := 0;
Loop
Fetch cf into M;
Exit when cf%notfound;
N := cf%rowcount;
Declare
Cursor cf is
select *
from emp;
M cf%rowtype;
Begin
Open cf;
Loop
fetch cf into M;
if cf%rowcount = 3 then
dbms_output.put_line(M.empno||'-'||M.ename||'-'||M.sal||'-'||M.deptno);
end if;
exit when cf%notfound;
End Loop;
End;
Example 3
Accepting the job from user and finally showing how many such jobs are there.
Declare
Cursor cf is
select *
from emp
where job ='&J';
M cf%rowtype;
N number;
J Emp.Job%type;
Begin
Open cf;
N := 0;
Loop
Fetch cf into M;
Exit when cf%notfound;
If cf%found then
N := N + 1;
End if;
End Loop;
Close cf;
If N > 0 then
dbms_output.put_line('Total number of job ' || J || ' is '|| N);
else
dbms_output.put_line('No such job');
End If;
End;
Example 4
Example 5) To see the first person( or first record entered) who has got salary
> 2800
Declare
Cursor cf is
select *
from emp
where sal > 2800;
M cf%rowtype;
Begin
Open cf;
Loop
fetch cf into M;
if cf%rowcount = 1 then
dbms_output.put_line(M.empno||'-'||M.ename||'-'||M.sal||'-'||M.deptno);
end if;
exit when cf%notfound;
End Loop;
End;
Cursor FOR Loop
u Implicitly declares its loop index as a record of %ROWTYPE,
u Implicitly opens the cursor
u Repeatedly fetches rows of values from the active set into fields in the record
u Implicitly closes the cursor when all rows have been processed or the loop is exited
u The statements in the loop construct are executed once for each row that satisfies
the query associated with the cursor name
u Cursor FOR loop is used to simplify coding
u No need of --
1)Open cursor
2)Fetch
3)Exit
4)Close cursor
Cursor FOR Loops Using Subqueries Cursor FOR Loops Using Subqueries
begin
For cf in (Select empno,ename,sal from emp)
Loop
dbms_output.put_line(cf.empno || '-' || cf.ename || '-' ||cf.sal);
End Loop;
end;
Implicit Cursors
• Automatically defined and opened, by Oracle, to process each SQL
statement
• most recently opened context area is referred to as a ‘SQL%’ cursor
u Although OPEN, CLOSE and FETCH statements cannot be used to manipulate the
SQL% cursor, the attributes can be used to access its context area
u Attributes evaluate to NULL, before the cursor is opened automatically
u The following four cursor attributes can be used to access the SQL%
cursor’s context area
u SQL%NOTFOUND
u SQL%FOUND
u SQL%ROWCOUNT
u SQL%ISOPEN
u SQL%NOTFOUND
u evaluates to TRUE if an INSERT, UPDATE or DELETE statement affected no
rows, else it evaluates to FALSE
u SQL%FOUND
u logical opposite of SQL%NOTFOUND
u evaluates to TRUE if an INSERT, UPDATE or DELETE affected one or more
rows, else it evaluates to FALSE
u SQL%ROWCOUNT
– returns the number of rows affected by an INSERT, UPDATE or DELETE
statement
u SQL%ISOPEN
– Oracle automatically closes an implicit cursor after executing its associated
SQL statement
– For an implicit cursor SQL%ISOPEN always evaluates to FALSE
If SQL%Found Then
dbms_output.put_line('Record found and it is deleted');
End If;
If SQL%NotFound Then
dbms_output.put_line('No record is present of the given name.');
End If;
End;
/*If no record is updated since the deptno supplied is wrong then giving
the customised error message.*/
If SQL%Rowcount = 0 then
dbms_output.put_line('No records are updated since the department number
entered is not in the table.');
End if;
Declare
Cursor cf is
select * from esal
For Update of sal;
M cf%rowtype;
Begin
Open cf;
Loop
Fetch cf into M;
exit when cf%notfound;
Else
M.Sal := 5000;
End If;
Update esal
set sal = M.Sal
Where Current Of cf;
End Loop;
End;
Cursors with Parameters
OPEN cursor_name(parameter_value,.....) ;
REF CURSORS
Limitations of a normal cursors are --
1) A PL/SQL program cannot pass a cursor as a parameter to another program.
2) A PL/SQL program can only open the cursor and process the information within
the program itself.
Package Specification –
End PRC;
Package Body –
End DeptDetails;
End PRC;
Introduction to Exceptions
u More than one exception can be handled in a single exception handler by separating
them with the keyword OR
EXCEPTION
WHEN NO_DATA_FOUND OR TOO_MANY_ROWS THEN
statements;
WHEN OTHERS THEN
statements;
END;
declare
n emp.ename%type;
s emp.sal%type;
begin
select sal into s
from emp
where ename = '&n';
dbms_output.put_line('Salary is '|| s);
Exception
When NO_DATA_FOUND then
dbms_output.put_line('No record');
end;
User-defined Exceptions
Begin
p := &p;
if p < 100 then
raise EX;
else
si := (p * n * r) / 100;
dbms_output.put_line('The Simple Interest is '|| si);
end if;
Exception
/*When EX then
dbms_output.put_line('The principle amt should be greater than or equal to
100.');*/
end;
--------------------------------------------------------------------------------------
RAISE_application_error
This can be used to create user defined error meaasge,which can be more
descriptive than named exceptions.
Syntax - :
Raise_application_error(error number,error message);
where error number is any parameter between -20,000 and -20,999.Error message
is text that is associated with this error. The message parameter must be less than 512
characters.
Example of Raise_application_error
declare
maths number;
Begin
maths := &maths;
declare
x number;
begin
x := '&x';
if x < 0 then
raise_application_error(-20009,'ty');
end if;
exception
when value_error then
dbms_output.put_line('ff');
end;
SQLCODE and SQLERRM
Example –
--------------------------------------------------------
Declare
verr number;
vmsg varchar2(100);
vsal emp.sal%type;
Begin
select sal into vsal
from emp;
Exception
When Others Then
verr := SQLCODE;
vmsg := SQLERRM;
Insert into errorlog
Values(verr, vmsg);
End;
=========================================================
===========================================
Advantages of Subprograms
u Provide Extensibility
– PL/SQL language can be tailored to suit the needs of the application
u Promote reusability and maintainability
– Once validated, they can be used with confidence in any number of
applications
– Simplifies maintenance/enhancement, as subprogram is only affected if
definition changes
u Provide Modularity
– Program can be broken down into manageable, well-defined logical modules
– Supports top-down design and stepwise refinement approach to problem
solving
u Aid in abstraction
– Allow mental separation from particulars
– Stubs allow programmers to defer definition of procedures/functions until
main program is tested and debugged
Procedures
-- While executing
--exec (1,'o',800) -----> (No deptno parameter given!!!)
OUT parameter
– allows values to be returned to the caller of a subprogram
– inside the subprogram it acts like an uninitialized variable
– actual corresponding parameter must be a variable; it cannot be a
constant or expression
– its value cannot be assigned to another variable or reassigned to
itself
IN OUT parameter
– allows initial values to be passed and returns updated values to the
caller
– inside the subprogram it acts like an initialized variable
– actual corresponding parameter must be a variable; it cannot be a
constant or expression
– can be assigned a value and its value can be assigned to another
variable
x := (x * x);
End;
variable ss number
exec scott.trial1(7499,:ss);
With AUTHID Current User
variable ss number
exec scott.trial2(7499,:ss);
=====================================================
==============================
Functions
u Subprogram that returns a value
u Have a RETURN clause
u Stored in database and can be invoked or called by any anonymous block
u Generally take parameters
u Datatype specifier in parameter declaration must be unconstrained
u Has two parts
u Specification
u begins with keyword FUNCTION, ends with RETURN clause
u Body
u begins with keyword IS, ends with keyword END followed by optional
function name
Syntax –
Format –
Calling a Function
Examples of Functions –
1)
a)
create or replace function eo ( n number)
RETURN char is
disp char(30);
Begin
If Mod(n,2) = 0 Then
disp := 'Number is even';
else
disp := 'Number is odd';
End If;
dbms_output.put_line(disp);
RETURN disp;
End;
TRIGGERS
u It is a stored PL/SQL program unit associated with a specific database table
u Oracle executes (fires) the trigger automatically whenever a given SQL operation
affects the table
u They are invoked implicitly
u They are useful for customizing a database
u They should be used only when necessary
u Can automatically generate derived column values
u Can prevent invalid transactions
u Can enforce complex security authorizations
u Can enforce referential integrity across nodes in a distributed database
u Can enforce complex business rules
u Can provide transparent event logging
u Can provide sophisticated auditing
u Can maintain synchronous table replicates
u Can gather statistics on table access
u Can derive column values automatically
u Can restrict DML operations to regular business hours
Syntax --
CREATE [OR REPLACE] TRIGGER <triggername>
BEFORE|AFTER
INSERT|DELETE|UPDATE OF <columnnames> ON <tablename>
[FOR EACH ROW]
WHEN (<condition>)
<PL/SQL Block>
u Name in the ON clause identifies the database table associated with the trigger
u The trigger event specifies the SQL DML statement (INSERT, DELETE or UPDATE)
that affects the table
u AFTER specifies that the trigger fires after the manipulation is done
u BEFORE specifies that the trigger fires before the manipulation is done
u By default, a trigger fires once per table
u FOR EACH ROW specifies that the trigger fires once per row
u For the trigger to fire, the boolean expression in the WHEN clause must evaluate to
TRUE
u REPLACE can be added to the CREATE statement to drop and re-create the trigger
automatically
CREATE TRIGGER flight_update
AFTER INSERT ON reservation
FOR EACH ROW
BEGIN
IF :new.class = ‘F’ THEN
statements;
ELSIF :new.class = ‘B’ THEN
statements;
END IF;
END;
u Prefix :new is a correlation name that refers to the newly updated column value
u Within a trigger, the :new and :old values of changing rows can be referenced
u A single trigger can handle more than one operation
u Use conditional predicates to identify the type of statement used to invoke the
section of code
Instead Of Triggers
insert into r
values(1,90);
insert into r
values(2,87);
Packages
u Database objects that group logically related PL/SQL types, objects and
subprograms
u They cannot be called, passed parameters to or nested
u There are two parts
– Specification
– Body
Advantages of Packages
u Modularity
– allows encapsulation of related types, objects and subprograms in a named
PL/SQL module
– easy to understand with simple, clear and well defined interfaces
– helps in application development
u Easier Application Design
– when designing applications, only interface information in package
specifications initially required
– can code and compile specification without body
– stored subprograms referencing the package can be compiled as well
– need not define package bodies until ready to complete the application
u Information Hiding
– can specify which types, items, and subprograms are public or private
– definition of private subprograms is hidden so that only the package (not the
application) is affected if the definition changes
– simplifies maintenance and enhancement and protects integrity of the
package
u Better performance
– when a packaged subprogram is called for the first time, the whole package is
loaded into memory
– later calls to related subprograms in the package require no disk I/O
Package Specification
u Is an interface to the applications
u Declares the types, variables, constants, exceptions, cursors and subprograms
available for use
u Holds public declarations, visible to the application
u Can be thought of as an operational interface
u Scope of the declarations are local to the database schema and global to the package
u Lists the package resources available to applications
u Created using CREATE PACKAGE command
Package Body
u Packaged objects and subprograms must be referenced using the dot notation
packagename.typename
packagename.objectname
packagename.subprogramname
E.g - DBMS_OUTPUT.PUT_LINE
Maintaining a Package
Examples of Packages –
Package Specification –
create or replace package pk1 is
procedure x(a number);
procedure y(b number);
procedure z(c number);
end;
Package Body –
create or replace package body pk1
is
procedure x(a number)
is
Begin
dbms_output.put_line('Procedure p1');
End x;
procedure y(b number)
is
Begin
dbms_output.put_line('Procedure p2');
End y;
/*Suppose in the package body if all the procedures are not written then it will
give error.*/
procedure z(c number)
is
Begin
dbms_output.put_line('Procedure p3');
End z;
End pk1;
-------------------------------
Using the Package pk1—
SQL > Execute PK1.X(4);
2) Use of global variable in a function and procedure –
Package Specification –
Package Body –
procedure n
is
Begin
if g >= 100 then
dbms_output.put_line('Discount is 20%');
else
dbms_output.put_line('Discount is 10%');
end if;
end n;
End pk2;
Declare
x number;
Begin
x := pk2.m(700);
pk2.n;
End;
3)
Use of Type in a Procedure –
Package Specification –
Package Body –
Package Specification –
b)
create or replace package body pk1
is
procedure p(a number, b number)
is
c number;
begin
c := a + b;
dbms_output.put_line(c);
end p;
begin
if z > 0 then
dbms_output.put_line('The number is positive');
else
dbms_output.put_line('The number is negative');
end if;
end p;
procedure p
is
begin
dbms_output.put_line('No parameter is passed');
end p;
end pk1;
Private Members
procedure pubproc
is begin
priv;
end;
end;
Collections
u Collections are similar to arrays available in most 3GLs
u A collection is an object that contains other objects of similar type
u It is an ordered group of elements of the same type
u Each element is identified by a unique subscript that determines its position in the
collection
Step 2 -
Type of a TABLE used as a data type of a column. This column is having nested
table.
Colors is the column having Color_tab_t type. The colors column is having the nested table.
Step 4 --
To retrieve color names through a PL/SQL block create a variable of Color_tab_t
type. Then fetch the nested table column into that variable for that row. Then
through loop show each color with the help of the variable.
To see all the colors available to Maruti car --
DECLARE
colorlist Color_tab_t;
BEGIN
SELECT colors INTO colorlist FROM cars
WHERE name = 'Maruti';
FOR i IN 1..colorlist.COUNT
LOOP
dbms_output.put_line( colorlist(i) );
END LOOP;
END;
VARRAY
Example – In a factory table there are workers using different tools. Each worker is using
say 3 numbers of tools. Thus if a single worker is taking 3 tools then that worker’s name will
come thrice in the table. So there will be data redundancy. Varrays will repeat values that
change for a particular column which will save the storage space.
Step 2 – Now creating array of this type to hold multiple (3) values
create type tool_va as
Varray(3) of tool_ty
Step 3 - Finally create a table having one of the column as the varray
column based on the varray type.
Updating VARRAYs
u Individual elements cannot be updated
u Entire VARRAY has to be updated if one of the elements has to be changed
SYNTAX
UPDATE <table_name>
SET <varray_column> = <varray_type_name>
(<typename>(attribute1_value,...),
<typename>(attribute2_value,...))
WHERE <condition>;
PL/SQL Records
Declare
TYPE empdetails IS RECORD
(eno Emp.Empno%type,
name Emp.Ename%type,
s Emp.Sal%type);
VE empdetails;
Begin
Declare
TYPE si IS RECORD
(p number,
n number,
r number := 4.5);
/* r variable of si type has been given value. */
VSI si;
x number;
Begin
VSI.p := 5000;
VSI.n := 6;
x := (VSI.p * VSI.n * VSI.r) / 100;
dbms_output.put_line(x);
End;
PL/SQL Tables
Example 1 –
SET SERVEROUTPUT ON
DECLARE
TYPE emp_table_type is table of
employees%ROWTYPE INDEX BY BINARY_INTEGER;
my_emp_table emp_table_type;
v_count NUMBER(3):= 104;
BEGIN
FOR i IN 100..v_count
LOOP
SELECT * INTO my_emp_table(i) FROM employees
WHERE employee_id = i;
END LOOP;
FOR i IN my_emp_table.FIRST..my_emp_table.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(my_emp_table(i).last_name);
END LOOP;
END;
Example 2
declare
Type discount is TABLE OF number
INDEX By Binary_Integer;
d discount;
Begin
d(5) := 90;
d(2) := 50;
d(8) := 70;
d(11) := 67;
d(14) := 68;
d(1) := 1;
d(23) := 5;
d(23) := 51;
dbms_output.put_line('The value at 23 index number is ' || d(23));
/*dbms_output.put_line('The value at index number 6 is ' || d(6));
dbms_output.put_line('The value at index number 2 is ' || d(2));
if d.EXISTS(6) Then
dbms_output.put_line(d(6));
else
dbms_output.put_line('There is no element in the sixth row');
end if;
d.delete(5);
dbms_output.put_line('The total number of elements in d are '|| d.count);
d.delete(11,14);
dbms_output.put_line('The total number of elements in d are '|| d.count);
d.delete;
dbms_output.put_line('The total number of elements in d are '|| d.count); */
end;
Dynamic SQL:
Dynamic SQL statements are stored in character strings built by your program at run time.
Such strings must contain the text of a valid SQL statement or PL/SQL block.
1) You want to execute a SQL data definition statement (such as CREATE), a data
control statement (such as GRANT), or a session control statement (such as ALTER
SESSION). In PL/SQL, such statements cannot be executed statically.
2) You want more flexibility. For example, you might want to defer your choice of
schema objects until run time. Or, you might want your program to build different
search conditions for the WHERE clause of a SELECT statement. A more complex
program might choose from various SQL operations, clauses, etc.
3) You use package DBMS_SQL to execute SQL statements dynamically, but you want
better performance, something easier to use, or functionality that DBMS_SQL lacks
such as support for objects and collections.
Using the EXECUTE IMMEDIATE statement:
EXECUTE IMMEDIATE dynamic_string
[INTO {define_variable[, define_variable]... | record}]
[USING [IN | OUT | IN OUT] bind_argument
[, [IN | OUT | IN OUT] bind_argument]...];
Except for multi-row queries, the string can contain any SQL statement (without the
terminator) or any PL/SQL block (with the terminator). The string can also contain
placeholders for bind arguments. However, you cannot use bind arguments to pass the
names of schema objects to a dynamic SQL statement.
Caution: You can execute a dynamic SQL statement repeatedly using new values for the
bind arguments. However, you incur some overhead because EXECUTE IMMEDIATE
re-prepares the dynamic string before every execution.
Example:
DECLARE
sql_stmt VARCHAR2(100);
plsql_block VARCHAR2(200);
my_deptno NUMBER(2) := 50;
my_dname VARCHAR2(15) := 'PERSONNEL';
my_loc VARCHAR2(15) := 'DALLAS';
emp_rec emp%ROWTYPE;
BEGIN
sql_stmt := 'INSERT INTO dept VALUES (:1, :2, :3)';
EXECUTE IMMEDIATE sql_stmt USING my_deptno, my_dname, my_loc;
With dynamic sql, we have SQL that is not known until run time. the PLSQL engine does
not know how many columns might be fetched, what tables will be accessed, what inputs
are expected. You, the programmer, must do more work to deal with this.
You use dynamic sql only when there is quite simply NO WAY to do it statically.
o speed
o ease of coding
o ease of maintenance
o automatic dependency tracking (if you statically reference something, it is recorded in
the data dictionary and you can query up that fact. If you dynamically reference it -- it is
NOT recordable)
o ease of debugging/testing (with dynamic sql, the query isn't generated until runtime --
will that query work? I don't know until i run EVERY possible combination. With STATIC
sql I know at compile time that its valid sql)
DBMS_SQL:
OPEN_CURSOR:
To process a SQL statement, you must have an open cursor. When you call the
OPEN_CURSOR function, you receive a cursor ID number for the data structure representing
a valid cursor maintained by Oracle.
PARSE :
Every SQL statement must be parsed by calling the PARSE procedure. Parsing the
statement checks the statement's syntax and associates it with the cursor in your program.
BIND_VARIABLE or BIND_ARRAY :
Many DML statements require that data in your program be input to Oracle. When you
define a SQL statement that contains input data to be supplied at runtime, you must use
placeholders in the SQL statement to mark where data must be supplied.
For each placeholder in the SQL statement, you must call one of the bind procedures,
BIND_VARIABLE or BIND_ARRAY, to supply the value of a variable in your program (or the
values of an array) to the placeholder. When the SQL statement is subsequently run, Oracle
uses the data that your program has placed in the output and input, or bind, variables.
EXECUTE:
Call the EXECUTE function to run your SQL statement.
FETCH_ROWS or EXECUTE_AND_FETCH :
The FETCH_ROWS function retrieves the rows that satisfy the query. Each successive fetch
retrieves another set of rows, until the fetch is unable to retrieve anymore rows. Instead of
calling EXECUTE and then FETCH_ROWS, you may find it more efficient to call
EXECUTE_AND_FETCH if you are calling EXECUTE for a single execution.
CLOSE_CURSOR :
When you no longer need a cursor for a session, close the cursor by calling
CLOSE_CURSOR.
What is the difference between pragma exception_init , and raise application error( which is
a subprogram from dbms_standard package).
ANSWER=>
pragma exception init turns an Oracle Error into a named exception. If a
database operation raises an ORA-00054 "resource busy", you would have to code:
....
exception
when others then
if (sqlcode=-54) then
.... deal with it.
else
RAISE;
end if;
if you pragma exception init'ed this error to some named exception RESOURCE_BUSY
, you can code:
....
pragma exception_init( resource_busy, -54 );
begin
....
exception
when resource_busy then
.... deal with it.
end;
If I just fling a named exception, the client gets the truly usless error
message "unhandled user defined exception". If I use raise_application_error --
the client gets whatever I send back.