Sie sind auf Seite 1von 92

PL-SQL

1. Introduction to PL/SQL.

2. Decision Making.

3. Loops.

4. Sub –blocks

5. Cursors.

6. Exceptions

8. Stored Procs

9. Stored functions.

10. Packages

11. Managing subprograms

12. Arrays.

13. Database Triggers

14. Advance Trigger concepts.

15. Ref cursor.

16. Dynamic SQL.


1. Introduction to PL/SQL.
• Procedural language SQL

• Complex processing like loops and IF condition.

• Also known as programming language of ORACLE

• PL SQL can be used for processing recordsets.(cursors) ,resultset.

• It can be used in SQL PLUS , oracle Forms, oracle Reports , oracle

Menus, oracle graphics.

Declare

Declarative section.

Begin

End

/*Program*/

Begin

--------

--------

Begin

--------

--------

Begin

--------

--------

End;

----------

-----------
End;

---------

---------

End;

Forward slash comes outside the outermost block.

No limit for block within a block. This is known as Block level language.

In a PL/SQL block, SQL commands like insert ,delete, rollback, commit,

select are used.

• DDL commands not allowed. eg. Create , drop table are not allowed.

• DCL commands not allowed eg. Grant , revoke cannot be done

• Create a table at SQL prompt

Create table tempp123

FIR number(8),

SEC varchar2 (25)

);

Anonymous Blocks

1.

Begin

Insert into tempp123 values(1,’Hello’);

Insert into tempp123 values(2,’Hello’);

End;

SQL> Insert into tempp123 values (1,’Hello’);

SQL> Insert into tempp123 values (2,’Hello’);


SELECT * FROM TEMPP123;

2. Declare

X number (4);

Begin

X := 100;

Insert into tempp123 Values (X, 'Hello');

End;

Select * from tempp123;

IN the above program, X is declared between Declare and Begin.Variable

declaration must be between Declare and Begin. “ : = ” is known as the

assignment operator.

3. cl scr

Delete from tempp123;

Declare

X number (4):= 100;

Begin

Insert into tempp123

Values (X, ‘Hello’);

End;

The entire program goes into the buffer.

4.

Declare

X number(4);
Begin

X := &salary;

Insert into tempp123

Values (X, ‘Hello’);

End;

Here value of salary is inputted by user. Value is asked for during

compilation and not at runtime.

5. Select * from tempp123;

Declare

X char(15) ;

Begin

X := ‘&ename’;

Insert into tempp123

Values (1, X);

End;

Enter the name of employee : Jack

Or

Enter the name of employee: 1056 /*This is not possible coz number to char

conversion is implicit but char to number is not implicit*/

7. Declare

X constant number (4):= 100;

Begin

Insert into tempp123

Values (X, ‘Hello’);


End;

Constant variable value can’t be changed anywhere in the program.

8. Declare

X number (8);

Begin

Select sal into X

From emp

Where fname like ‘Mandar’;

Insert into tempp123

Values (X, ‘Mandar’);

End;

Value of sal from emp table is transferred into tempp123 table and

displayed. Select in some variable name is allowed .

Output  FIR SEC

5000 King

9. Declare

X number(8);

Y varchar2(35);

Hra number(6,2);

Begin

Select sal , job into X ,Y

From emp

Where lower(fname) like ‘mandar’;


Hra:= 0.10 * X ;

Insert into tempp123 Values (X, ‘Mandar’);

Insert into tempp123 Values (Hra, Y);

dbms_output.put_line (‘Salary of Mandar is ’|| X ||’and Hra is =’ ||Hra);

End;

dbms_output.put_line can be used to test program. It is not PL/SQL

command. It’s a package developed by ORACLE .In the

“dbms_output.put_line (X || ‘King’ || Hra || ‘ ‘ || Y);” number to char

conversion is implicit . If date is there then TO_CHAR is required. For this

stmnt to work:

SQL> SET SERVEROUTPUT ON

Case 1

Declare

X number (4);

Case 2

10. Declare

X emp.sal%type;

Y emp.job%type;

Begin

Select sal,job into x ,y

from emp

where fname like ‘Mandar’;

Insert into tempp123

Values (x, y);

End;
“ x emp.sal%type ” defines that datatype of x is same as that of the

datatype of sal in emp table.

11. Declare

x emp% rowtype;

Begin

Select * into x

From emp

Where fname like ‘Mandar’;

Insert into tempp123

Values (x.sal, x.job);

End;

/
fname sal job
rowtype is used to store entire row

x.fname

x.sal x.job

Create user-defined structure (RECORD) in PL/SQL:

Declare

Type pqr is record

a emp.sal%type,

b emp.job%type

);

x pqr;

Begin

Select sal, job into x


From emp

Where fname = ‘Mandar’;

Insert into tempp123 values (x.a, x.b);

End;

Create table emp_profile

(empno number,sal number(8),job varchar2(30));

Declare

Type abc is record

a emp.sal%type,

b emp.job%type

);

Type emp_profile_pqr is record

l number(4),

m abc

);

x emp_profile_pqr ;

Begin

Select empno, sal, job into x.l,x.m.a, x.m.b

From emp

Where fname like ‘Mandar’;

Insert into emp_profile values (x.l,x.m.a, x.m.b);

End;
2. DECISION MAKING

IF STMNT:

1. Declare

X number (8);

Begin

Select sal into x

from emp

Where fname like ’Mandar’;

If X>4000 then

Insert into tempp123 values (X,’HIGH SAL’);

else

insert into tempp123 values (X,’LOW SAL’);

end if;

End;

IF – ELSIF

2. Declare

X number (8);

Begin

Select sal into X

From EMP

Where fname like ’Mandar’;

IF X>30000 then

Insert into tempp123 values (x,’HIGH SAL’);


elsif X<30000 and X>4000 then

Insert into tempp123 values (x,’MED SAL’);

else

Insert into tempp123 values (x,’low SAL’);

END IF;

End;

3. Declare

X Boolean; /* boolean can be used only in PL SQL –Multiline

comments */

Begin

X:=false; --edited by abc (single line comment)

If X then

Insert into tempp123 Values (1,’positive’);

Elsif not X then

Insert into tempp123 values (0,’negative’);

End if;

End;
LOOPS

WHILE LOOP :

1. Declare

X number (4) := 1;

Begin

While X <10

Loop

Insert into tempp123

Values (X , ‘Hello’);

X:=x+1;

EXIT;

End loop;

End;

Note: Explain EXIT keyword.

DO WHILE LOOP:

5. Declare

X number(4) := 1;

Begin

Loop

Insert into tempp123

Values (X, ‘Do-While’);

Exit when X>5;


X := X+1;

End loop;

End;

Executes the loop atleast once.

FOR LOOP:

• Automatic incrementation of variable.

• For variable need not be declared.

• Step value cannot be changed .Always increments by 1.

If u want to change step value then use ‘while’ loop.

6. Declare

Begin

For X in 1..10

Loop

Insert into tempp123

Values (X, ‘Hello’);

End loop;

End;

• Here X is only read only variable u can’t initialize and assign value to

it.

• 1.. 10 should contain exactly two dots only.


7. Declare

X number(4):= 100;

Begin

Insert into tempp123

Values (X, ‘before for’);

For X in 1..10

Loop

Insert into tempp123

Values (X, ‘For-Loop’);

End loop;

Insert into tempp123

Values (X, ‘after for’);

End;

Output  FIR SEC

100 before for

1 Hello

: “

9 “

100 after for

8. Declare

Y number (4):= 10;

Z number (4):= 20;

Begin

For X in Y..Z

Loop
Insert into tempp123

Values (X, ‘Hello’);

End loop;

End;

For more user friendly program we can use:

For X in X…&Y // additional dot is taken as delimiter

output  Enter X: 16

Y: 25

OR

For X in &X ..&Y // blank space in between also acts as a delimiter.

Declare

Y number(4) ;

Z number(4);

Begin

For X in &Y...&Z

Loop

Insert into tempp123

Values (X, ‘Hello’);

End loop;

End;

10. For X in 1.5..9.3

It rounds it to 2 and 9 and then execute.


Begin

for X in 1..10

loop

for Y in 1..X ----INNER LOOP

loop

Insert into tempp123

Values (X, ‘Hello’);

End loop;

End loop;

End;

Note: -- single comment (don’t put & in comment)

/*multilane comment*/

GOTO stmnt:

• Conditional or unconditional transfer of control.

1. Declare

X number (4):= 1;

Begin

Insert into tempp123

Values (X, ‘A’);

Goto abc;

<<pqr>>

Insert into tempp123

Values (X, ‘B’);

X := X+1;

<<abc>>

Insert into tempp123


Values (X, ‘C’);

If X < 3 then

Goto pqr;

End if;

End ;

output  FIR SEC

1 A

1 C

1 B

2 C

2 B

3 C

NOTE: If large no.of GOTO stmnt in program then it is called SPAGHETTI

CODE.

Practical use: when u’ve large no. of nested loops use goto stmnt to come

out.

Rules fro GOTO stmnt:

• Cannot transfer control into a loop. Reverse is allowed.

• Cannot transfer control into IF condition . Reverse is allowed .

• GOTO should always transfer control to some executable

stmnt.Same things hold true for if..endif condition.


SUB – BLOCKS

1. Declare

X number (4):= 1;

Begin

Insert into tempp123

Values (X, ‘before sub’);

Declare

Y number (4):= 2;

Begin

Insert into tempp123

Values (X, ‘in sub BLOCK’);

X: = X+Y;

End;

Insert into tempp123

Values (X, ‘after sub’);

End;

Output  FIR SEC

1 before sub

1 in sub

3 after sub

• Parent cannot access child’s variables . Reverse is allowed.

• Child can alter parents variables (will affect globally).


2. Declare

X number (4):= 1;

Begin

Insert into tempp123

Values (X, ‘before sub’);

Declare

X number (4):= 2;

Begin

Insert into tempp123

Values (X, ‘in sub’);

End;

Insert into tempp123

Values (X, ‘after sub’);

End;

output  FIR SEC

1 before sub

2 in sub

1 after sub

3. <<abc>>

Declare

X number (4) := 1;

Begin

Declare

X number (4) := 2;

Begin
Insert into tempp123

Values (abc.X, ‘in sub’); -- this will access parents X.

end;

end;

• To access global X use labels.

• One child cannot access another child’s variable.


CURSORS(V.V.V IMP)

Cursors are of two types:

1. Implicit Cursor:

• Oracle created

• To check the status of last DML stmnt(To check whether successful

or not)

• Name of implicit cursor is SQL

• Maintain logs / audit trails of all DML operations

1. Declare

X number(4);

Begin

Update emp set sal = sal+1 where deptno = 110;

If SQL%found then

X:= SQL%rowcount;

Insert into tempp123 values (X,’updated’);

End if;

End;

Sql%found returns a true value if the last DML is successful.

Output  3 updated

2. Declare

X number(4);

Begin
Delete from EMP where deptno = 20;

If SQL%found then

X:= SQL%rowcount;

Insert into tempp123 values (X,’deleted’);

End if;

End;

Output  2 deleted

3. Declare

X number(4);

Begin

Insert into emp select * from semp; --semp structure similar to emp.

If SQL%found then

X := SQL%rowcount;

Insert into tempp123 values (X,’inserted’);

End if;

End;

Output  4 inserted

• In single insert all rows are inserted to emp .

2. Explicit cursor:

• It’s a type of variable.

• Used for handling multiple rows and process them row by row.

• Used for storing data temporarily.

• It’s a memory area .

• It is used for record locking.


1. Declare

Cursor C1 is select * from emp where deptno=10;

X emp%rowtype;

Begin

Open C1; ---will open the cursor and will populate it with the above

select statement

Loop

Fetch C1 into X;

Exit when C1%notfound; ---%notfound returns true if the last fetch is

unsuccessful

Insert into tempp123

Values (X.empno, X.fname);

End loop;

Close C1; ---will free up the memory used by c1

End;

Cursor attributes:-

a) %notfound r

b) %found  .i.e TRUE if last fetch

is successful & false if it is unsuccessful

c) %isopen  returns true value whenever cursor is open

d) %rowcount  no.of rows fetched by cursor so far


Declare

Cursor C1 is select * from emp;

X emp%rowtype;

Y number;

Begin

Open C1;

Loop

Fetch C1 into X;

Exit when C1%notfound;

insert into tempp123

Values (X.empno, X.fname);

End loop;

Y := C1%rowcount;

Dbms_output.put_line(‘value of y is ‘||Y);

Close C1;

End;

-------

if C1% isopen then

close C1;

endif;

Before opening cursor check if it is already open then close it & again it

can be opened. This concept is used for Resetting the cursor pointer.
Steps in cursor operation:

• Declaration of variable X (intermediate variable for fetching row)

• Open cursor (fires the select statement in the cursor and populates

the data).

• Fetch one row at a time to X from cursor

• Include proper condition to exit;otherwise it goes in an infinite loop.

• Close cursor to free memory in RAM.

FOR LOOP Cursor:-

8. Declare

Cursor C1 is select fname, sal from emp;

Begin

For X in C1

Loop

Insert into tempp123 values(X.sal, X.fname);---ACTION

End loop;

End;

Advantages of a For Loop Cursor:-

1. Here we do not declare the for variable, it will have same structure of

C1.

2. No need to open C1. No need to fetch manually its automatic.

3. Exit condition also not required.

4. The for loop cursor automatically gets destroyed .No need of close

C1.
Declare

Cursor C1 is select fname, sal from emp;

Begin

For X in C1

Loop

Insert into tempp123 values(X.sal, X.fname);

End loop;

End;

Output tempp123

10. Declare

Cursor C1 is select * from emp

where deptno= &deptnum;

Begin

For X in C1

Loop

Insert into tempp123 values (X.sal, X.fname);

End loop;

End;

This is static to make it dynamic proc++, projava.

OV7 onwards parameters can be passed to cursor.

11. Declare

Cursor C1 (dd number)

is select * from emp

Where deptno=dd;
Begin

For X in C1(10)

Loop

Insert into tempp123 values (X.sal, X.fname);

End loop;

For X in C1(30)

Loop

Insert into tempp123 values (X.sal, X.fname);

End loop;

End;

Declare

cursor C1(dd number)

is select * from emp

where deptno=dd;

Begin

For X in C1(&d1)

Loop

Insert into tempp123 values (X.sal, X.fname);

End loop;

For X in C1(&d2)

Loop

Insert into tempp123 values (X.sal, X.fname);

End loop;

End;
13. Declare

Cursor C1 (dd number, ss number)

Is select * from EMP

Where deptno=dd and sal>ss;

Begin

For X in C1(10,29000)

Loop

Insert into tempp123 values (X.sal, X.fname);

End loop;

End;

14. Default arguments in a cursor:-

Declare

cursor C1(dd number, ss number default 9000)

is select * from emp

where deptno=dd and sal>ss;

Begin

For X in C1(10)

Loop

Insert into tempp123 values(X.sal, X.fname);

End loop;

End;
15. Declare

Cursor C1 is select fname, sal+1 salary

from emp;

Begin

For X in C1

Loop

Insert into tempp123 values(X.salary, X.fname);

End loop;

End;

C1

A 5001

B 6001

C 7001

D 8001

E 9001

• In cursor defn if u’ve computed field,or an function like sum,ltrim

then alias should be given so as to refer that column.

If alias not given then u cannot refer that field,but block will still

execute.

17. Declare

Cursor C1 is select * from dept;

Cursor C2 is select * from emp;

Begin

For X in C1

Loop
For Y in C2

Loop

If X.deptno = Y.deptno then

Insert into tempp123 values(Y.empno, X.dname);

End if;

End loop;

End loop;

End;

 C2 emp

EMPNO ENAME SAL DEPTNO


1 A 5000 1
2 B 6000 1
3 C 7000 1
4 D 8000 2
5 E 9000 2

 C1 dept

Deptno Dname Loc


1 Trn Mumbai
2 Exp Delhi
3 Mrktng Calcutta
• There is no upper limit on no.of cursors opened simultaneously.

• INIT.ORA  startup file of oracle server, text file around 350

parameters. One of the parameters is

OPEN_CURSORS = 250 set to whatever values it allows that many

cursors to open simultaneously. Default value is 25.

Note: For each deptno in C1 open C2 , go through C2, close C2, advance

C2, C1 pointers, open C2 continue to slow.

Output:

1 trn
2 trn

3 trn

4 exp

5 exp

Faster programs:

18.

Declare

Cursor C1 is select * from dept;

Cursor C2(dd number) is select * from emp

Where deptno=dd;

Begin

For X in C1

loop

For Y in C2 (X.deptno) -- only those rows with dept no in C2 hence

faster.

Loop

Insert into tempp123 values(Y.empno, X.dname);

End loop;

End loop;

End;

Here no unnecessary comparisons of records .

19. Fastest:

Declare

Cursor C1 is select empno, dname

From emp, dept

Where dept.deptno = emp.deptno;


Begin

For X in C1

Loop

Insert into tempp123 values(X.empno, X.dname);

End loop;

End;

gives u same output but is much more faster than before two ways.

20. Declare

Cursor C1 is Select * from emp;

Begin

For X in C1

Loop

If X.sal > 7000 then

Update emp set sal= sal+1;

End if;

End loop;

End;

 Sal column of emp table is updated.

21. Declare

Cursor C1 is select * from emp for update;

Begin

For X in C1

Loop
If X.sal > 7000 then

Update emp set sal = sal +1 where current of C1;

End if;

End loop;

End;

• For update record locking. Manual locking of all the rows.

22. Declare

Cursor C1 is select * from emp for update;

Begin

For X in C1

Loop

If X.sal > 47000 then

Delete from emp where current of C1;

End if;

End loop;

End;

ARRAYS

• To store multiple elements of the same datatype.

• Temporary table

• In PL SQL arrays are single dimension only (multidimension arrays

not allowed in OV7 but OV7 onwards it allows).


• Can ‘ve array only for a scalar datatype. Composite datatype not

allowed. Cannot‘ve an array of structure in OV7./ But OV7 onwards it

allows.

10 20 30
A

• In PL SQL subscript has to be binary integer for variables (for

constants base 10 is allowed). In above A(1),A(2),A(3).

• Array size is dynamic. Add elements array size increases

automatically. Remove elements array size decreases automatically.

EXCEPTION

Exceptions are of foll. Types:-

1. Predefined Exception.

2. User defined Exception.

3. Pragma Exception init.

4. Raise Application error.

Declare

Begin

end

Declare

Begin
====

Exception when too_many_rows then

END;

A. Predefined exception:

 Oracle created (already available in the system).

 Automatically invoked as and when specific error takes place

1 Declare

X number(8);

Begin

Select sal into X from emp

Where fname = ‘Mandar’;

Insert into tempp123 values (X, ‘King’);

Exception when too_many_rows then

Insert into tempp123 values (1, ‘Too many rows Error’); -- error

handling routine

End;

update emp set fname ='Mandar' where fnAME='raj';

o/p 

FIR SEC

1 Hello

Note:-

Within the error handling routine, all PL SQL stmnts are allowed.
Control can’t be transferred from error handling routine to any other

part of the block.

2. Declare

X number (8);

Begin

Select sal into X from emp

Where fname = ‘Jack’;

Insert into tempp123 values (X, ‘Jack’);

Exception when no_data_found then

Insert into tempp123 values (1, ‘no data found’); --error handling

routine

When others then

Insert into tempp123 values (2,’others’);

End;

3. Declare

X number(4);

Begin

X := 10000;----size exceeded

Exception when value_error then

Insert into tempp123 values (1, ‘value error’); --error handling routine

End;

eg: x number(6,2)

x := 1000.786
4. Declare

X number (4);

Begin

X := ‘cal’; --datatype mismatch gives an exception

Exception when value_error then

Insert into tempp123 values (1, ‘value error’); --error handling routine

End;

value_errror : char value in numeric variable in an expression.

5. Declare

X char(4);

Begin

X := 1000;

End;

It doesn’t give error bcoz number to char conversion is implicit.

6. Declare

X number(4);

Begin

Insert into tempp123 values (‘mumbai’, ‘city’);

Exception when invalid_number then /*error char value in numeric

col.*/

Insert into tempp123 values (1, ‘invalid number’); --error handling

routine

End;
/

Note:-- when working with an expression i.e. x number; x:=’abc’; then it

gives a value error,but with an insert statement it gives invalid number.

7. Declare

X number(4) :=10;

Y number(4) :=0;

a number;

b varchar2(32767);---max value in PL/SQL

Begin

X := X/Y;

Exception when zero_divide then

a := sqlcode;

b := sqlerrm;

dbms_output.put_line(‘oracle says’||sqlerrm);

Insert into tempp123 values (a, ‘zero divide’); -- error handling routine

End;

9. Declare

X number(4) :=10 ;

Begin

Insert into tempp123 values (X,’before sub block’);

Declare

X number(4) ;

Begin

X:=10000;

Insert into tempp123 values (X,’in sub’);

Exception when value_error then


Insert into tempp123 values (1, ‘sub error’);

End;

Insert into tempp123 values (X,’After sub’);

Exception when value_error then

insert into tempp123 values (1, ‘main error’);

End;

o/p 

FIR SEC

10 before sub

1000 in sub

10 after sub

Can have exception in each block.

10. Remove sub –block exception

Declare

X number (4) :=10 ;

Begin

Insert into tempp123 values (X,’before sub’);

Declare

X number (4) :=10 ;

Begin

X :=10000;

Insert into tempp123 values (X,’in sub’);

End;

Insert into tempp123 values (X,’After sub’);


Exception when value_error then

Insert into tempp123 values (1, ‘main error’);

End;

If sub block exception is removed then search for exception handler in

parent block.

o/p 

FIR SEC

10 before sub

1 main error

• Errors can be trapped only between begin and end .

Question:-If error in declare section,then exception can’t handle

it.Then how to handle it?

Declare

X number(4) :=1000000 ;

Begin

Insert into tempp123 values (X,’before sub’);

Declare

X number(4) ;

Begin

X:=1000;

Insert into tempp123 values (X,’in sub’);

Exception when value_error then

Insert into tempp123 values (1, ‘sub error’);

End;
Insert into tempp123 values (X,’After sub’);

Exception when value_error then

insert into tempp123 values (1, ‘main error’);

End;

Declare

X number(4) :=10 ;

Begin

Insert into tempp123 values (X,'before sub');

Declare

X number(4):=100000;

Begin

---X:=100000;

Insert into tempp123 values (X,'in sub');

Exception when value_error then

Insert into tempp123 values (1, 'sub error');

End;

Insert into tempp123 values (X,'After sub');

Exception when value_error then

insert into tempp123 values (1, 'main error');

End;

To take care of this, outside of declare , put dummy parent block.

Few more Predefined exceptions

1. too_many_rows
2. No_data_found

3. Value_error

4. Invalid_number

5. Zero_divide

6 invalid_cursor

Try to close a cursor, when it is not open.

7. cursor_already_open

Try to open a cursor, which is already open.

8. DUP_value on index

Try to insert a duplicate value in a column that has a unique index on it.

9. logon_denied

Logging to oracle with an invalid username and password

10.Program_Error

(Internal PL/SQL error, some files are not installed)

11. Rowtype_mismatch

Fetch c1 into x

(x has a different datatype )

12. storage_error.

(memory problem)

B. User defined exception

• User created

• datatype

• Has to be raised explicitly

• For enforcing business rules.

Eg:
11. Declare

X number(8);

abc exception;

Begin

Select sal into X from emp

Where fname = ‘Mandar’;

if X > 5000 then

raise abc;

end if;

Insert into tempp123 values (X,’<=5000’);

exception when abc then

insert into tempp123 values (X,’>5000’);

end;

o/p  6000 X>5000

600 X<=5000

12. Declare

X number (8) := 10;

abc exception;

Begin

Insert into tempp123 values (X,’before sub’);

Declare

X number(8);
abc exception;

begin

Select sal into X from emp

Where fname = ‘Mandar’;

if X > 5000 then

Raise abc;

End if;

Insert into tempp123 values (X,’in sub’);

Exception when abc then

insert into tempp123 values (X,’sub error’);

end;

Insert into tempp123 values (X,’after sub’);

Exception when abc then

Insert into tempp123 values (X,’main error’);

end;

Remove the exception from the child block

Declare

X number (8) := 10;

abc exception;

Begin

Insert into tempp123 values (X,’before sub’);

Declare

X number(8);
begin

Select sal into X from emp

Where fname = ‘Mandar’;

if X > 5000 then

Raise abc;

End if;

Insert into tempp123 values (X,’in sub’);

end;

Insert into tempp123 values (X,’after sub’);

Exception when abc then

Insert into tempp123 values (X,’main error’);

End;

C. Pragma Exception:- It is used to associate an oracle error number with a

user defined exception

Declare

X number (8);

abc exception;

Pragma exception_init (abc,-01843);

Begin

Select sal into X from emp

Where hiredate = ’10-MMM-95’;

Exception when abc then

Insert into tempp123 values (1, ‘Hello’); --error handling routine

dbms_output.put_line('oracle says errcode is '||sqlcode||’and message

is’ ||sqlerrm);

End;
/

• In above program if error occurs pragmas automatically raise abc

no need of explicitly raising.

Raise Application error:-

Declare

Begin

Delete from emp where empno=99;

If sql%notfound then

Raise_application_error(-20001,’Emp doesn’’t exist’);

End if;

End;

Note:--

Error number :-it can range from –20,000 to –20,999.

Message:-character string upto 2048 bytes.

It is used to create a library of errors

STORED PROCEDURE

• It is a collection of statements.

• Only a single copy is brought into the RAM (program code shared by

all the users) when multiple users execute the same stored proc.

• It’s a pre-compiled code(stored).

• Can be called in SQL Plus, PL SQL Forms, Reports, Menus,

Graphics, JAVA, .NET,VB,

Creating stored Procedures:-

SQL> Create or replace procedure p1


As

Begin

Insert into tempp123 values(1, ‘p1’);

end;

MESSG: Procedure created.

3. SQL> execute P1

It execute stored procedure abc

o/p FIR SEC

1 Hello

4. SQL> Select * from Tempp123;

o/p  1 Hello

TO CALL IN PL SQL :

Declare

=======

Begin

=========

P1 ;

End;

declare

begin

p1;

end;

To call procedure from other schema:


Username. Procedurename

Same way can be called in forms, Reports.

SQL> create or replace procedure p2

as

X number(4) := 10;

Begin

insert into tempp123 values (X, ‘p1’);

insert into tempp123 values (X, ‘p2’);

commit;

End;

• Local variables, cursors, exceptions can be written in stored

procedure.(Same as a PL/SQL Block :-No ddl)

• Can pass parameters.

Creating Procedures with Parameters:-

Actual parameters.---the one we pass in the call


Formal parameters.---the one in the definition.

Types of parameters(vvvvvvimp)

IN- Used to pass values to the procedures OR functions.


Can have a default value.
It is call by reference.
It can be constant or a variable.

OUT- It is used to return values from the Procedures/Functions to the


calling env.
Cannot have defaults values
Must be a variable.
Call by VALUE
IN OUT-Passes a value from the calling environment into the procedure and
a possibly different value from the procedure back to the calling
environment using the same parameter

Call by VALUE
Cannot have defaults values
Must be a variable.

SQL> create or replace procedure p3 (x in number)

As

Begin

Insert into tempp123 values (X, ‘Hello’);

End;

create or replace procedure p3 (x number)

As

Begin

insert into tempp123 values (X, ‘Hello’);

End;

Note:-Never declare sizes for the parameters.

================

Execute p3 (10); // while running

• Parameters passed to stored procedure can be IN , OUT, INOUT

parameters.

Create or replace procedure query_emp


(p_id in emp.empno%type,
p_name out emp.fname%type,
p_salary out emp.sal%type,
p_deptno out emp.deptno%type)
is
Begin
Select fname, sal, deptno
into p_name, p_salary, p_deptno
from emp
Where empno = p_id;
end query_emp;

Variable g_name varchar2(25)


Variable g_sal number
Variable g_deptno number

Execute query_emp(2, :g_name, :g_sal, :g_deptno);

Print g_name
Print g_sal
Print g_deptno

IN OUT Parameters:-

Calling environment FORMAT_PHONE procedure


p_phone_no '(800)633-0575' '8006330575'

CREATE OR REPLACE PROCEDURE format_phone


(p_phone_no IN OUT VARCHAR2)
IS
BEGIN
p_phone_no := '(' || SUBSTR(p_phone_no,1,3) ||
')' || SUBSTR(p_phone_no,4,3) ||
'-' || SUBSTR(p_phone_no,7);
END format_phone;
/

VARIABLE g_phone_no VARCHAR2(15)

BEGIN
:g_phone_no := '8006330575';
END;
/
PRINT g_phone_no
EXECUTE format_phone (:g_phone_no);

PRINT g_phone_no

Examples of stored procedure:-


Create or replace procedure sim_int(p number, t number, r number)

As

si number(6,2);

amt number(7,2);

begin

si := p * t * r / 100;

amt := p + si;

dbms_output.put_line(‘interest =’ || si);

dbms_output.put_line(‘amount =’ || amt);

Exception when value_error then

dbms_output.put_line(‘value too large . Try again’ );

end;

Exec sim_int(5000,3,9);

2. SQL> create or replace procedure delete_emp(x number)

as

y number(4);

abc exception;

Begin

select count(*) into y from emp

where empno = x;

if y = 0 then

raise abc;
end if;

delete from emp where empno = x;

-- commit;

dbms_output.put_line(‘employee deleted successfully’);

Exception when abc then

dbms_output.put_line(‘employee does not exists’);

end;

Now calling the above procedure in another program.

Begin

dbms_output.put_line (‘before procedure’);

delete_emp (1001);

dbms_output.put_line (‘after procedure’ );

End;

Begin

dbms_output.put_line(‘before procedure’);

delete_emp(1);

dbms_output.put_line(‘after procedure’ );

End;

Rollback;

• When you make changes in procedure it has to be recreated.

• Thus we don’t give user direct access to table but through

procedure.

• This is called as procedural encapsulation.


• SQL> select object_name from user_objects -- gives all the

stored ts

Where object_type = ‘PROCEDURE’;

• Now to make changes in stored procedure

SQL> select TEXT from user_source

Where type = ‘PROCEDURE’

And name = ‘SIM_INT’;

SQL> DESC SIM_INT

Describes procedure.

STORED FUNCTIONS

• Global functions(Can be accessed from any Front end)

• Stored in the database in compiled format

• Can be called in PL/SQL , forms, reports, menus, graphics.java,.net

• Can be called at SQL prompt.

1 SQL> create or replace function fabc(y number)

return number
as

Begin

Return y * y;

End;

Function created.

To call the above function in some other PL SQL program:

2. SQL> Declare

x number(4);

begin

x := fabc(10);

Insert into tempp123 values (x, ‘after abc’);

End;

In the above example , we have to equate with some variable because

function returns a value.Hence , it cant be called at SQL prompt.

select fabc(10) from dual;

3. SQL> create or replace function pqr(y number)

return Boolean

As

Begin

if y > 5000 then

Return true;

else

Return false;

end if;
End;

4. SQL> Declare

x number(4);

begin

x := &x;

if pqr(x) then

Insert into tempp123 values (x, ‘>5000’);

else

Insert into tempp123 values (x, ‘<=5000’);

end if;

end;

• If condition is returning Boolean value then directly function name

can be used.

Ex:

create or replace function alltrim(X char)

return char

as

begin

return ltrim(rtrim(x));

end;

CREATE OR REPLACE FUNCTION tax(p_value IN NUMBER)


RETURN NUMBER IS
BEGIN
RETURN (p_value * 0.08);
END tax;
/
SELECT empno, lname, sal, tax(sal)
FROM emp
WHERE deptno = 10;

SELECT empno,lname,sal, tax(sal),deptno


FROM emp
WHERE tax(sal)>(SELECT MAX(tax(sal))
FROM emp WHERE deptno = 30)
ORDER BY tax(sal) DESC;

Restrictions on Calling Functions from SQL Expressions(v.v.imp)


To be callable from SQL expressions, a user-defined
function must:

• Accept only IN parameters

• Accept and return only valid SQL data types, not PL/SQL like boolean

• Functions called from SQL , cannot contain DML statements.

CREATE OR REPLACE FUNCTION dml_call_sql


RETURN NUMBER
IS
BEGIN
INSERT INTO emp(empno, lname,
hiredate, job, sal)
VALUES(111, 'employee 1',
SYSDATE, 'SA_MAN', 2000);
RETURN 1;
END;
/

declare

x number;

begin

x:=dml_call_sql;

end;

Select * from emp where empno=111;

Create or replace function query_empf


(p_id in emp.empno%type,
p_name out emp.lname%type,
p_salary out emp.sal%type,
p_deptno out emp.deptno%type)
return number
is
begin
select lname, sal, deptno
into p_name, p_salary, p_deptno
from emp
where empno = p_id;
return 1;
end query_empf;

Declare
g_name varchar2 (50);
g_sal number;
g_deptno number;
x number;
begin
x:= query_empf(2, :g_name, :g_sal, :g_deptno);
end;

Print g_name;
Print g_sal;
Print g_deptno;

Difference between Procedure and Function( v.v.imp)

1. A Function has to return one value.

2. A Function can be called from sql prompt.

3. Is invoked a part of an expression.

Managing Subprograms
Suppose the EMPLOYEES table is located within the scott schema, and
there is a user named Green.

Green can access the EMPLOYEES table only by way of the QUERY_EMP
procedure that Scott created, which queries employee records.

Definer‘s Rights

Scott provides the EXECUTE object privilege to Green on the QUERY_EMP


procedure.
By default the PL/SQL subprogram executes under the security domain of
the owner.
This is referred to as definer's-rights. Because Scott has direct privileges to
EMPLOYEES table and has created a procedure called QUERY_EMP, Green
can retrieve information from the EMPLOYEES table by using the
QUERY_EMP procedure. Now Green will access the EMPLOYEES table in
scott schema

Imp Note:-

If Green also has an EMPLOYEES table, the QUERY_EMP procedure will


not reference this table but rather the EMPLOYEES table that Scott’s
schema can reference.

Using Invoker's-Rights

The procedure executes with the privileges of the user.

CREATE or replace PROCEDURE query_employee


(P_id IN employees.employee_id%TYPE,
p_name OUT employees.last_name%TYPE,
p_salary OUT employees.salary%TYPE,
p_comm OUT employees.commission_pct%TYPE)
AUTHID CURRENT_USER
IS
BEGIN
SELECT last_name, salary,
commission_pct
INTO p_name, p_salary, p_comm
FROM employees
WHERE employee_id=p_id;
END query_employee;
/

AUTHID DEFINER (Default option)

Invoker’s-Rights

To ensure that the procedure executes using the security of the executing
user, and not the owner,
use AUTHID CURRENT_USER. This ensures that the procedure executes
with the privileges and
schema context of its current user ie invoker .
Default behavior, as shown on the previous page, is when the procedure
executes under the security
domain of the owner; but if you wanted to explicitly state that the
procedure should execute using
the owner's privileges, then use AUTHID DEFINER.
Note:- AUTHID is introduced in Oracle8i. In previous versions of the Oracle
server, the behavior was based
on definer’s rights as described on the previous page.

List All Procedures and Functions

SELECT object_name, object_type


FROM user_objects
WHERE object_type in ('PROCEDURE','FUNCTION')
ORDER BY object_name;

List the Code of Procedures and Functions


SELECT text
FROM user_source
WHERE name = 'QUERY_EMPLOYEE'
ORDER BY line;

CREATE OR REPLACE PROCEDURE log_execution


IS
BEGIN
INSERT INTO log_table (user_id, log_date)
-- wrong
VALUES (USER, SYSDATE);
END;
/
Example
Given the above code for LOG_EXECUTION, there will be a compile error
when you run the
script for compilation.

List Compilation Errors by Using


USER_ERRORS

SELECT line || '/' || position POS, text


FROM user_errors
WHERE name = 'LOG_EXECUTION'
ORDER BY line;

SHOW ERRORS
PACKAGES

• Collection of related procedures and functions

• Make a call to any one of them. (proc/ Func.)and the entire

package(ALL PROGRAM UNITS IN THE PACKAGE) comes in to

the server RAM.

• Execution will be very fast (as in RAM).

• The entire package will remain in the server RAM till you end

your session. Even if you are not using it.


• When RAM gets full then internally LRU makes the RAM

free.Least recently used is removed.

• Package is stored in compiled format.

Package definition/specification:

Create or replace package delemp

as

Procedure del_emp (mdeptno number);

End;

Package body:-

SQL> Create or replace package body delemp

As

Function count_emp(mdeptno number)

return number

is

X number (4);

Begin

Select count(*) into x from emp

where deptno=mdeptno;

Return x;

End;

Procedure del_emp(mdeptno number)

is

X number(4);

begin
X := count_emp(mdeptno);

if X >0 then

delete from emp where deptno= mdeptno;

end if ;

end;

End ;

The package body consists of from “ begin to end” .

OUTPUT: Package created.

To execute:

SQL> execute package name .proc name

SQL> execute delemp.del_emp(10)

• Procedure first call’s function and check whether a dept. has

an employee. Now a procedure call’s other procedure or function if

they are at hard disk then slow.But if in a package then they are

both

in RAM.

In PLSQL , we have :

1. Declare

=======

Begin

========

delemp.delete_emp(10);

========
end;

To call function independently :

Select delemp.count_emp(10) from dual;

Declare

Y number (4);

Begin

Y: = delemp.count_emp(10);

Insert into tempp123

values (Y,’employee’);

End;

• The data ( program units & variables) present in package definition

is globally available.

(USED TO CREATE GLOBAL VARIABLES )

• The data present in package body is locally available

Forward Declaration:-

Create or replace package pg1


as
Procedure pt1(x number);

End;

Create or replace package body pg1

As

Procedure pr2; -- forward declaration

Procedure pt1(x number)

Is

Begin
Dbms_output.put_line(‘Pt1’);

Pr2;

End;

Procedure pr2

Is

Begin

Dbms_output.put_line(‘Pr2’);

End;

End;

Exec pg1.pt1(10);

Exec pg1.pr2; ----private procedure

6. SQL> Create or replace package pabc

As

Procedure one;

Procedure two;

End;

Create or replace package body pabc

As

Procedure one

Is

X number (4) :=1; /* Here X is a local variable*/

Begin

Insert into tempp123

Values (X,’A’);

X := X+1;
end;

Procedure two

is

X number (4) := 2;

Begin

Insert into tempp123

Values (X,’B’);

X: = X+1;

End;

End;

SQL> execute pabc.one

SQL> execute pabc.two

SQL> execute pabc.one

Execute Pabc.two is faster than execute Pabc.one because it is in RAM.

OUTPUT:

1 A

2 B

1 A

7. SQL> Create or replace package pgabc

as

Procedure one;

Procedure two;

end;

Create or replace package body pgabc

as
X number (4) := 0;

Procedure one

is

begin

X:= X+1;

Insert into tempp123

Values (X,’A’);

end;

Procedure two

is

begin

X := X+1;

Insert into tempp123

values (X,’B’);

Exception when others then

Dbms_output.put_line(‘hello’);

end;

end;

SQL> execute pgabc.one

SQL> execute pgabc.two

SQL> execute pgabc.one

OUTPUT :

1 A

2 B

3 A
• In the above program X is a global variable declared above the

procedure. Now global X remains in the server RAM. It becomes a

static variable.

• One can’t access variable X outside the package. To do so:

8. Create or replace package p_abc

as

X number(4):=0;

Procedure one;

Procedure Two;

end;

To access X :

9. Declare

Y number (4);

Begin

Y := p_abc.X + 1;

Insert into tempp123

values(Y,’Hello’);

p_abc.X:= p_abc.X + 1;

end;

• Ideally, always have all RELATED procedure & function in a package.

• The procedure and function in a package are normally called the

database triggers.

Procedure/Function Overloading in Packages:-


1. Overloading on basis of number of arguments.

Create or replace package p_overld

As

Procedure one(x number ,y number);

Procedure one (v varchar2);

end;

Create or replace package body p_overld

As

Procedure one(x number,y number)

is

begin

Insert into tempp123

Values (1,'proc_number');

End;

Procedure one (v varchar2)

Is

Begin

Insert into tempp123

Values (1,'proc_varchar');

End;

End;

Exec p_overld.one(‘a’);

Exec p_overld.one(1,2);

2. Overloading on basis of data type of arguments:-

Create or replace package p_overld


As

Procedure one(x number);

Procedure one(v varchar2);

end;

Create or replace package body p_overld

as

Procedure one(x number)

is

begin

insert into tempp123

Values(1,'proc_number');

end;

Procedure one(v varchar2)

is

begin

Insert into tempp123

Values (1,'proc_varchar');

End;

End;

Exec p_overld.one(‘a’);

Exec p_overld.one(1);

3. Overloading on basis of the order of arguments:-

Create or replace package p_overld

as
Procedure one(x number ,y varchar2);

Procedure one (v varchar2, m number);

end;

Create or replace package body p_overld

As

Procedure one(x number varchar2)

is

begin

Insert into tempp123

Values (1,'proc_number');

End;

Procedure one (v varchar2, m number)

Is

Begin

Insert into tempp123

Values (1,'proc_varchar');

End;

End;

Exec p_overld.one(1,‘a’);

Exec p_overld.one(‘a’,2);

PG1

P1  N1 N2 DEFAULT

P2  N1
Note:-

One proc (p1) in a package pg1 has two number parameters and the

second one is default parameter.

Second proc (p1) in a package pg1 has one number parameter.

Can they be overloaded.

Its gives a runtime error.( USING POSITIONAL METHOD)

Solution :

Overloading using named Method:-

Create or replace package pg12


As
Procedure p123(x number);
Procedure p123 (n number);
End;

Create or replace package body pg12


As
Procedure p123(x number)
As
Begin
dbms_output.put_line (‘x’);
End;
Procedure p123 (n number)
As
Begin
dbms_output.put_line (‘n’);
End;
End;

exec pg12.p123(x=>1);
exec pg12.p123(n=>2);

Advantages of Packages:-

1. Improved Performance.
2. Overloading.
3.GLOBAL VARIABLES

create or replace function f1


(x number)
return number
as
begin
dbms_output.put_line('f1');
return 1;
end;
/

declare
x number;
begin
x:=f1(x=>5); ---CAN be used when we are not sure abt the order of
arguments
end;
/

Database Triggers

Database Triggers :

• The procedures and functions in package are frequently called through

database triggers.

• Database triggers are present from OV7 onwards.

• It is a routine (set of commands) that gets executed automatically when

some events occur.


• Difference between procedure and trigger is that procedure needs to be

called while trigger is called automatically.

• Number of events that take place are :

Before insert -ST1 & RT1

After insert-ST2 & RT2

Before delete

After delete

Before update

After update

Database (DML) triggers are of 2 types:

a. Statement level trigger Fires once for every DML statement.

b. Row level trigger Fires once for each and every row, in the DML

statement.

DML STATEMENT:

Update emp

Set sal =sal + 100

Where deptno =10;

---3ROWS UPDATED.

ST1:ONCE

RT1:THRICE

As there are 6 events and 2 types a max of 12 triggers are possible on a

given table.

Statement level Trigger:-.

SQL> create or replace trigger t1

before insert

on emp
Begin

Insert into tempp123

Values (1,’inserted’);

end;

insert into emp(empno,sal) values(23,22222);

• Ideally there is a procedure which inserts into tempp123 faster than

other routines.

• In a trigger all PL SQL statements (except rollback & commit).

SQL> create or replace trigger abc

Before insert

on emp

Begin

Insert into tempp123

Values (1,’inserted’);

Commit;

end;

insert into emp(empno,sal) values(213,22222);

SQL> Rollback;

Now temp data commited but the insert in emp is roll backed

This leads to inconsistency of data.

Compare the difference between Statement level trigger and Row level

trigger:
Create or replace trigger t4 -----row level trigger

before update

on emp for each row

begin

insert into tempp123

values (1,’row level updated’);

end;

Create or replace trigger t5

before update

on emp

begin

Insert into tempp123

values (1,’statement level updated’);

End;

Update emp

Set sal=sal+100

Where deptno=10;

Row level insert:-

create or replace trigger abc

Before insert on emp

for each row

Begin

Insert into tempp123

Values (1,'inserted');

end;

insert into emp select * from copy_emp;


Bind variables in Triggers:-

SQL> create or replace trigger T6

Before insert

On emp

Begin

Insert into tempp123

Values (:new.sal, :new.fname);

end;

Insert into emp(empno,fname,sal,deptno) values(1,'xyx',3000,10);

• This can be used to create two copies of emp ie. One can maintain

multiple copies of a table during insert . This concept is called DATA

MIRRORING. Such as tempp123 table acts as a shadow table

• One can’t pass parameter to a trigger. But “:new.sal” these are global

variables . (Bind variables)

• “:new” can be used only in DB triggers(only Row level).

Create table deptot

(deptno number,

saltot number);

insert into deptot values(10,0);

insert into deptot values(20,0);

insert into deptot values(30,0);

SQL> create or replace trigger T7


before insert

on emp for each row

Begin

Update deptot set saltot = saltot + :new.sal

where deptno = :new.deptno;

end;

Insert into emp(empno,fname,sal,deptno) values(8,’deepak’,5600,10);

Database triggers for delete :

Create or replace trigger T8

before delete

on emp for each row

begin

insert into tempp123

values (1,’deleted’);

end;

Create or replace trigger T9

before delete

on emp

begin

insert into tempp123

values (1,’ st level deleted’);

end;

Create or replace trigger t9

Before delete
On emp for each row

Begin

Insert into tempp123

Values (:old.sal, :old.fname);

End;

:old delete

:new  insert

:old + :new - update

Delete emp where deptno =10;

• For every row of dept the old value is stored in tempp123.This is

similar to Recycle Bin.

• Stores old values in the case of delete .Now tempp123 table called as

History Table.

• “ :old “ can be used with row level DB triggers . Read only global

bind variables.

Note:-

Insert  :new

Delete :old

Update  :new and :old both.

SQL> create or replace trigger T10

before delete

on emp for each row

begin

update deptot set saltot = saltot - :old.sal

where deptno = :old.deptno;


end;

Database triggers for update :

1. SQL> create or replace trigger T11

before update

on emp for each row

begin

insert into tempp123

values (:old.sal, :old.fname);

insert into tempp123

values (:new.sal, :new.fname);

end;

That is both (:old, :new) can be used for update. Thus , both history table

and shadow table maintained in case of update.

2. SQL> update emp

set sal = sal+100

where deptno=20 ;

create or replace trigger T12

before update

on emp for each row

begin

update deptot set saltot = saltot - :old.sal + :new.sal

where deptno = :old.deptno;

end;

/
3. SQL> update emp

set job=’Clerk’

Where empno= 1;

Now sal is not accessed in the emp table even then triggerT12 is invoked.

This will not affect the data but unnecessary processing will take place.

To avoid this unnecessary processing:

4. SQL> create or replace trigger T13

before update of sal

on emp for each row

begin

update deptot set saltot = saltot - :old.sal + :new.sal

where deptno = :old.deptno;

end;

• Now the triggers fires only when sal is updated

• This is only in case of update that we can be specific.

5. SQL> update emp

set sal=27000

Where empno= 1;

6. SQL> create or replace trigger T14

before update of sal, deptno

on emp for each row

begin

if updating ('deptno') then

Update deptot
set saltot = saltot - :old.sal

Where deptno = :old.deptno;

Update deptot

Set saltot =saltot +:new.sal

Where deptno= :new.deptno;

else

Update deptot

set saltot = saltot + :new.sal - :old.sal

where deptno = :old.deptno;

end if;

end;

UPDATE EMP

SET DEPTNO=30

Where deptno =10;

update emp

set sal =20000

where empno=1

This will fire only if deptno, sal are updated.

• Updating() = it is a function which is used only with DB triggers.

Returns a Boolean value.

Now again trigger fires unnecessary processing is done. To avoid this

we‘ve

Note:- the above trigger fires even when salary is not changed.
To avoid that:

8. SQL> create or replace trigger xyz

before update of sal, deptno

on emp for each row

when (old.sal <> new.sal or old.deptno <> new.deptno)

begin

if updating (‘deptno’) then

Update deptot

Set saltot = saltot - :old.sal

where deptno = :old.deptno;

Update deptot

Set saltot = saltot + :new.sal

where deptno = :new.deptno;

else

update deptot

set saltot = saltot + :new.sal - :old.sal

where deptno = :old.deptno;

end if;

end;

In the above SQL trigger, we do not use “ ; “ before begin statement.

The old tablename is destroyed when it enters in the begin block and then

drop.

9. SQL> create or replace trigger xyz

Before insert or delete or update of sal, deptno

on emp for each row


Begin

if inserting then

insert into tempp123 values(1,’inserting’);

elsif deleting then

Raise_application_error (-20001, ‘deletion not allowed’);

elsif updating(‘deptno’) then

insert into tempp123 values(1,’updating’);

end if;

end;

Insert into emp(empno,fname,sal,deptno) values(8,’deepak’,5600,10);

• Everything within one trigger is possible .

Therfore 12 triggers down to 4 triggers.

Triggers can also contain exceptions :

Create or replace trigger t5

before update

on emp

begin

Insert into tempp123

values (1,’statement level updated’);

exception when others then

null;
End;

Update emp

Set sal=sal+100

Where deptno=10;

11.SQL> delete from emp;

output:

ORA_20001 deletion not allowed

This can be possible to preserve security.

• Trigger can be used for validations. Security can be maintained

using grant and revoke.

• Conditional security can be enforced through trigger. For eg: if day is

Sunday then deletion is not possible.

12. SQL> drop trigger abc;

• When table is dropped all triggers dropped automatically.

• On delete cascade is internally a trigger.

13. SQL> alter trigger xyz disable;

14. SQL> alter trigger xyz enable;

Mutating tables :

If in a Trigger, we try to access the same row which we are updating ,we get

mutating table error.

Create or replace trigger abc

Before insert or update of sal on emp

For each row

Declare

v_minsal number;

v_maxsal number;
Begin

select min(sal),max(sal) into v_minsal,v_maxsal from emp

where deptno=:new.deptno;

End;

Update emp

Set sal=sal+100

Where deptno=20;

1 20

2 20

Hierarchy of execution (******)

1. Before insert statement level trigger.

2. Before insert row level trigger.

3. After insert row level

4. After insert statement level

Advanced Trigger Concepts


Creating Triggers on DDL Statements

CREATE [OR REPLACE] TRIGGER trigger_name


timing
[ddl_event1 [OR ddl_event2 OR ...]]
ON {DATABASE|SCHEMA}
trigger_body

Create or replace trigger st1_sch


before create
on schema
Begin
Insert into tempp123 values (1,’create trigger’);
End;
Conn system/excellent

Create or replace trigger st1_db


before Create
on database
begin
Insert into tabc values(1,’create trigger’);
end;

When you specify ON SCHEMA, the trigger fires for the specific user.

If you specify ON DATABASE, the trigger fires for all users.

DDL triggers fire only if the object being created is a cluster, function,
index, package, procedure, role, sequence, synonym, table, tablespace,
trigger, type, view, or user.

LOGON and LOGOFF Trigger Example:-

Create or replace trigger logon_trig


after logon on schema
begin
Insert into tempp123 values (1,’log on’);
end;
/

Create or replace trigger logoff_trig


before logoff on schema
begin
insert into tempp123 values(1, ‘log off’);
end;
/

CALL Statements in a trigger

Create or replace trigger log_employee


before insert on emp
call p1
/

Insert into emp(empno,fname,sal,deptno) values(8,’deepak’,5600,10);

Note: There is no semicolon at the end of the CALL statement.

Implementing Triggers
You can use trigger for:
• Security
• Auditing
• Data integrity
• Referential integrity
• Computing derived data automatically

1. Security

Create or replace trigger secure_emp


before insert or update or delete on emp
Declare
v_dummy varchar2(1);
begin
if (to_char (sysdate, 'dy') in ('sat','wed',’thu’))then
raise_application_error (-20506,'deletion not allowed on sat.');
end if;
end;
/

Delete emp;

2. Auditing by Using a Trigger


• Write the audit trail to a user-defined audit table

3. Enforcing Data Integrity

Create or replace trigger check_salary


before update of sal on emp
for each row
when (new.sal < old.sal)
begin
raise_application_error (-20508, 'cannot decrease salary.');
end;
/

4. Enforcing Referential Integrity

Create or replace trigger cascade_updates


after update of deptno on dept
for each row
declare
x number;
begin
update emp
set emp.deptno=:new.deptno
where emp.deptno=:old.deptno;
end;
/

update dept set deptno=20 where deptno=30;

possible only when u have no fk constraints between emp and dept

If FK constraints are present then update will fail.


5. Computing Derived Data

alter table dept


add total_sal number;

Update dept
set total_sal=(select sum(sal)
from emp
where emp.deptno =dept.deptno);

Create or replace procedure increment_salary


(p_id in dept.deptno%type,
p_salary in dept.total_sal%type)
is
begin
Update dept
set total_sal = nvl (total_sal, 0)+ p_salary
where deptno = p_id;
End increment_salary;

Create or replace trigger compute_salary


after insert or update of sal or delete on emp
for each row
Begin
if deleting then
increment_salary (:old.deptno,(-1*:old.sal));
elsif updating then
increment_salary(:new.deptno,(:new.sal-:old.sal));
else increment_salary(:new.deptno,:new.sal); --insert
end if;
end;

Insert into emp(empno,sal,deptno) values (11,8000,10);


update emp set sal =10000 where empno=2 and deptno =10;
delete emp where empno=2 and deptno=10;

PL/SQL Tables(Arrays)
Create table emp_test
(empno number,ename varchar2(30));

Example 1:-

Declare
TYPE emp_plsqltab1 IS TABLE OF char(30) INDEX BY BINARY_INTEGER;
e emp_plsqltab1;
i binary_integer:=1;
ioCursor c1 is
Select empno, fname from emp;
Begin
for x in c1
loop
e(i):=x.fname;
insert into emp_test values(1,e(i));
i:=i+1;
end loop;
end;

Example 2:-

Declare
Type emp_rec is record (empno number, ename varchar2 (30) );
TYPE emp_plsqltab IS TABLE OF emp_rec INDEX BY BINARY_INTEGER;
e emp_plsqltab;
i binary_integer:=1;
Cursor c1 is
Select empno, fname from EMP;
Begin
For x in c1
Loop
e(i).empno:=x.empno;
e(i).ename:=x.fname;
Insert into emp_test values(e(i).empno,e(i).ename);
i:=i+1;
end loop;
end;

Note: Binary integar is used to store integers.


Range is 2 billion.

REF Cursor
A Cursor is a memory area; a Ref Cursor is a pointer to that.

A ref cursor can be passed a parameter to a procedure.

A ref cursor is used to return a set of records from the procedure to the
front end. (Note a normal cursor cannot be used).

The select statement of a ref cursor can be modified dynamically.

Create or replace package emp_data


as
type empcurtyp is ref cursor return emp%rowtype;
Procedure open_emp_cv (emp_cv in out empcurtyp,ch number);
end;
/

Create or replace package body emp_data


as
Procedure open_emp_cv (emp_cv in out empcurtyp,ch number) is
begin
if (ch=1) then
open emp_cv for select * from emp where deptno=10;
elsif (ch=2) then
open emp_cv for select * from emp where deptno=20;
end if;
end open_emp_cv;
End emp_data;
/

Create or replace procedure b1(p_choice in number)


is
empcurtyp1 emp_data.empcurtyp;--cursor variable like emp_cv
e emp%rowtype;
begin
emp_data.open_emp_cv(empcurtyp1,p_choice);
loop
fetch empcurtyp1 into e;
exit when empcurtyp1%notfound;
dbms_output.put_line (e.empno);
dbms_output.put_line (e.fname);
end loop;
End;
/

Dynamic SQL
Dynamic SQL:

• Is a SQL statement that contains variables that can


change during runtime.

• Enables general-purpose code to be written. Generic code.

SQL statements go through various stages:

Parse
Every SQL statement must be parsed. Parsing the statement includes
checking the statement's syntax and validating the statement, ensuring
that all references to objects are correct, and ensuring that the relevant
privileges to those objects exist.

Bind
After parsing, the Oracle server knows the meaning of the Oracle statement
but still may not have enough information to execute the statement. The
Oracle server may need values for any bind variable in the statement. The
process of obtaining these values is called binding variables.

Compile & Execute


At this point, the Oracle server has all necessary information and
resources, and the statement is executed.

Fetch
In the fetch stage, rows are selected(ie cursor is formed and returned)
and ordered (if requested by the query).

DBMS_SQL Package

The DBMS_SQL package is used to write dynamic SQL


in stored procedures and functions.

1. Use OPEN_CURSOR to establish an area in memory to process a SQL


statement.
2. Use PARSE to establish the validity of the SQL statement.
3. Use the EXECUTE function to run the SQL statement. This function
returns the number of row processed.
4. Use CLOSE_CURSOR to close the cursor.(free up the memory)

CREATE OR REPLACE PROCEDURE delete_all_rows


(p_tab_name IN VARCHAR2, p_rows_del OUT NUMBER)
IS
Cursor_name INTEGER;
BEGIN
cursor_name := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE(cursor_name, 'DELETE FROM '||p_tab_name,

DBMS_SQL.NATIVE );

p_rows_del := DBMS_SQL.EXECUTE (cursor_name);

DBMS_SQL.CLOSE_CURSOR(cursor_name);
END;
/
VARIABLE deleted NUMBER
EXECUTE delete_all_rows('emp', :deleted)

EXECUTE IMMEDIATE Statement

Dynamic SQL Using EXECUTE IMMEDIATE

CREATE OR REPLACE PROCEDURE del_rows


(p_table_name IN VARCHAR2,
p_rows_deld OUT NUMBER)
IS
BEGIN
EXECUTE IMMEDIATE 'delete from '||p_table_name;
p_rows_deld := SQL%ROWCOUNT;
END;
/

VARIABLE deleted NUMBER


EXECUTE del_rows('tempp’,:deleted)
PRINT deleted

Exec immediate can be used to perform ddl in procedures,func,packages:


CREATE OR REPLACE PROCEDURE dsql_ddl


IS
BEGIN
EXECUTE IMMEDIATE 'create table cvv (col2 number)’;
END;

Das könnte Ihnen auch gefallen