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> SQL> Insert into tempp123 values (1,’Hello’); 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 5000 SEC 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 rowtype is used to store entire row sal job

x.fname x.sal 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 x.job

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; 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; */ /* boolean can be used only in PL SQL –Multiline

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 100 1 : 9 100 8. Declare Y number (4):= 10; Z number (4):= 20; Begin For X in Y..Z Loop SEC

before for Hello “ “ after for

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 1 1 1 2 2 3 A C B C B C SEC

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 1 1 3 • • SEC before sub in sub 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 1 2 1 3. <<abc>> Declare X number (4) := 1; Begin Declare X number (4) := 2; Begin SEC before sub in sub after sub

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 b) %found r  .i.e TRUE if last fetch is successful & false if it is unsuccessful c) %isopen d) %rowcount  returns true value whenever cursor is open  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 B C D E • 5001 6001 7001 8001 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 1 2 3 4 5  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 ENAME A B C D E SAL 5000 6000 7000 8000 9000 DEPTNO 1 1 1 2 2

• •

2 3 4 5 Faster programs: 18. Declare

trn trn exp exp

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.

• A 10 20 30

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’); handling routine End; / update emp set fname ='Mandar' where fnAME='raj'; o/p  FIR 1 Note:Within the error handling routine, all PL SQL stmnts are allowed. SEC Hello -- error

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’); 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; / --error handling

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 col.*/ Insert into tempp123 values (1, ‘invalid number’); --error handling routine End; /*error char value in numeric

/ 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 10 1000 10 SEC before sub in sub 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 10 1 • SEC before sub 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 • • • • Eg: User created datatype Has to be raised explicitly For enforcing business rules.

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 600 X>5000 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 1 SEC 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 stored ts Where object_type = ‘PROCEDURE’;

-- gives all the

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; Begin Insert into tempp123 Values (X,’A’); X := X+1; /* Here X is a local variable*/

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 2 3 A B 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  P2  N1 N1 N2 DEFAULT

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 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 Fires once for each and every row, in the DML

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 2 20 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;

Sign up to vote on this title
UsefulNot useful