38
PL/SQL PL/SQL stands for Procedural Language/SQL.PL/SQL extends SQL by adding control Structures found in other procedural language.PL/SQL combines the flexibility of SQL with Powerful feature of 3 rd generation Language. The procedural construct and database access Are present in PL/SQL.PL/SQL can be used in both in database in Oracle Server and in Client side application development tools. Advantages of PL/SQL Support for SQL, support for object-oriented programming,, better performance, portability, higher productivity, Integration with Oracle a] Supports the declaration and manipulation of object types and collections. b] Allows the calling of external functions and procedures. c] Contains new libraries of built in packages. d] with PL/SQL , an multiple sql statements can be processed in a single command line statement. Oracle Supports PL/SQL version 8.0.4.0.0 PL/SQL Datatypes Scalar Types BINARY_INTEGER ,DEC,DECIMAL,DOUBLE ,,PRECISION,FLOAT,INT,INTEGER,NATURAL, NATURALN,NUMBER, NUMERIC, PLS_INTEGER,POSITIVE,POSITIVEN,REAL,SIGNTYPE, SMALLINT,CHAR,CHARACTER,LONG,LONG RAW,NCHAR,NVARCHAR2,RAW,ROWID,STRING, VARCHAR,VARCHAR2, Composite Types TABLE, VARRAY, RECORD LOB Types BFILE, BLOB, CLOB, NCLOB Reference Types REF CURSOR BOOLEAN, DATE DBMS_OUTPUT.PUT_LINE : It is a pre-defined package that prints the message inside the parenthesis ATTRIBUTES Allow us to refer to data types and objects from the database.PL/SQL variables and Constants can have attributes. The main advantage of using Attributes is even if you Change the data definition, you don’t need to change in the application. %TYPE It is used when declaring variables that refer to the database columns. Using %TYPE to declare variable has two advantages. First, you need not know the exact datatype of variable. Second, if the database definition of variable changes, the datatype of variable changes accordingly at run time. 1

PL SQL Material

Embed Size (px)

DESCRIPTION

Oracle Plsql Material

Citation preview

PL/SQL

PL/SQL stands for Procedural Language/SQL.PL/SQL extends SQL by adding control Structures found in other procedural language.PL/SQL combines the flexibility of SQL with Powerful feature of 3 rd generation Language. The procedural construct and database access Are present in PL/SQL.PL/SQL can be used in both in database in Oracle Server and in Client side application development tools.

Advantages of PL/SQL

Support for SQL, support for object-oriented programming,, better performance, portability, higher productivity, Integration with Oracle

a] Supports the declaration and manipulation of object types and collections.b] Allows the calling of external functions and procedures.c] Contains new libraries of built in packages.d] with PL/SQL , an multiple sql statements can be processed in a single command line statement.

Oracle Supports PL/SQL version 8.0.4.0.0

PL/SQL Datatypes

Scalar TypesBINARY_INTEGER ,DEC,DECIMAL,DOUBLE ,,PRECISION,FLOAT,INT,INTEGER,NATURAL, NATURALN,NUMBER, NUMERIC, PLS_INTEGER,POSITIVE,POSITIVEN,REAL,SIGNTYPE, SMALLINT,CHAR,CHARACTER,LONG,LONG RAW,NCHAR,NVARCHAR2,RAW,ROWID,STRING, VARCHAR,VARCHAR2, Composite TypesTABLE, VARRAY, RECORD

LOB TypesBFILE, BLOB, CLOB, NCLOB

Reference TypesREF CURSOR

BOOLEAN, DATE

DBMS_OUTPUT.PUT_LINE :

It is a pre-defined package that prints the message inside the parenthesis

ATTRIBUTES

Allow us to refer to data types and objects from the database.PL/SQL variables and Constants can have attributes. The main advantage of using Attributes is even if you Change the data definition, you don’t need to change in the application.

%TYPE

It is used when declaring variables that refer to the database columns.Using %TYPE to declare variable has two advantages. First, you need not know the exact datatype of variable. Second, if the database definition of variable changes, the datatype of variable changes accordingly at run time.

%ROWTYPE

The %ROWTYPE attribute provides a record type that represents a row in a table (or view). The record can store an entire row of data selected from the table or fetched from a cursor or strongly typed cursor variable.

CONTROL STRUCTURES

1

Conditional Control

Sequence of statements can be executed based on a certain condition using the if statement.There are three forms of if statements, namely, if then,if then else and if the Elsif.

ITERATIVE CONTROL

A sequence of statements can be executed any number of times using loop constructs.Loops can be broadly classified into:

Simple Loops , For Loops , While Loops

Simple LoopsKey Word loop should be placed before the first statement in the sequence and the key word end loop after the last statement in the sequence.

EXIT : It is a command that comes out of the loop.

While Loop This statement includes a condition associated with a sequence of statement. If the Condition evaluates to true, then the sequence of statements will be executed, and again Control resumes at the beginning of the loop else the loop is bypassed and control passes To next statement.

For LoopThe number of iterations for a while loop is unknown until the loop terminates, whereas The number of iterations in a for loop is known before the loop gets executed. The for loop statement specifies a range of integers, to execute the sequence of statements once for each integer.

REVERSE: Reverse key word is used to print the values from upper bound to lower bound.

EXCEPTION

An Exception is raised when an error occurs. In case of an error then normal execution stops and the control is immediately transferred to the exception handling part of the PL/SQL Block.

Exceptions are designed for runtime handling, rather than compile time handling. Exceptions improve readability by letting you isolate error-handling routines.

TypesPre-defined Exception, User-defined Exception

USER – DEFINED EXCEPTIONS User – defined exception must be defined and explicitly raised by the user

EXCEPTION_INIT A named exception can be associated with a particular oracle error. This can be used to trap the error specifically.

PRAGMA EXCEPTION_INIT(exception_name, Oracle_error_number);The pragma EXCEPTION_INIT associates an exception name with an Oracle,error number. That allows you to refer to any internal exception by name and to write a specific handler

RAISE_APPLICATION_ERRORThe procedure raise_application_error lets you issue user-defined error messages from stored subprograms. That way, you can report errors to your application and avoid returning unhandled exceptions.

To call raise_application_error, you use the syntax

raise_application_error(error_number, message[, {TRUE | FALSE}]);where error_number is a negative integer in the range -20000 .. -20999 and message is a character string up to 2048 bytes long.

2

PRE – DEFINED EXCEPTIONS

USER DEFINED EXCEPTION - EG

3

DECLAREout_of_balance EXCEPTION;

BEGINIF ... THEN

RAISE out_of_balance; -- raise the exceptionEND IF;

EXCEPTIONWHEN out_of_balance THEN

-- handle the errorEND;

PRAGMA EXCEPTION_INIT – EGS

DECLAREdeadlock_detected EXCEPTION;PRAGMA EXCEPTION_INIT(deadlock_detected, -60);

BEGIN...EXCEPTION

WHEN deadlock_detected THEN-- handle the error

END;

Handling Raised Exceptions

When an exception is raised, normal execution of your PL/SQL block or subprogram stops and control transfers to its exception-handling part, whichis formatted as follows:

EXCEPTIONWHEN exception_name1 THEN -- handlersequence_of_statements1

WHEN exception_name2 THEN -- another handlersequence_of_statements2

...WHEN OTHERS THEN -- optional handler

sequence_of_statements3

Using SQLCODE and SQLERRM

For internal exceptions, SQLCODE returns the number of the Oracle error. The number that SQLCODE returns is negative unless the Oracle error is no data found, in which case SQLCODE returns +100. SQLERRM returns the corresponding error message. The message begins with the Oracle error code.

Unhandled ExceptionsPL/SQL returns an unhandled exception error to the host environment, which determines the outcome.

When Others

It is used when all exception are to be trapped.

CURSORS

Oracle allocates an area of memory known as context area for the processing of SQL statements. The pointer that points to the context area is a cursor.

TYPES1 ] Static Cursor

EXPLICIT IMPLICIT

2] Dynamic Cursors3] REF Cursors.

Merits1] Allowing to position at specific rows of the result set.2] Returning one row or block of rows from the current position in the result set. 3] Supporting data modification to the rows at the current position in the result set.

4

TYPES

1] STATIC CURSOR

SQL statement is determined at design time.

A] EXPLICIT

EXPLICIT CURSOR -- Multiple row SELECT statement is called as an explicit cursor.

Usage - If the SELECT statement returns more that one row then explicit cursor should be used.

Steps Declare a cursor Open a cursor Fetch data from the cursor Close the cursor

Syntax CURSOR <CURSOR NAME> IS <SELECT STATEMENT> OPEN <CURSOR NAME> FETCH <CURSOR NAME> INTO <COLUMN NAMES> CLOSE <CURSOR NAME>

EXPLICIT CURSOR ATTRIBUTES %FOUND (Returns true if the cursor has a value) %NOTFOUND (Returns true if the cursor does not contain any value) %ROWCOUNT (Returns the number of rows selected by the cursor) %ISOPEN (Returns the cursor is opened or not)

CURSOR FOR LOOPSA cursor FOR loop implicitly opens a cursor, fetches the rows and closes the cursor automatically.

SYNTAX FOR <RECORD NAME> IN <CURSOR NAME> LOOP STATEMENTS END LOOP;

To refer an element of the record use <record name.column name>

EXPLICIT CURSOR WITH FOR LOOP

DECLARECURSOR C1 IS SELECT EMPNO,ENAME,SAL FROM EMP;

BEGINFOR ROW1 IN C1LOOP

DBMS_OUTPUT.PUT_LINE(ROW1.EMPNO);DBMS_OUTPUT.PUT_LINE(ROW1.ENAME);

END LOOP;END;

EXPLICIT CURSOR WITH FOR LOOP USING SUBQUERIES

BEGINFOR ROW1 IN (SELECT EMPNO,ENAME,SAL FROM EMP)LOOP

DBMS_OUTPUT.PUT_LINE(ROW1.EMPNO);DBMS_OUTPUT.PUT_LINE(ROW1.ENAME);

END LOOP;END;

EXPLICIT CURSOR ROW POSITIONING

DECLARECURSOR C1 IS SELECT EMPNO,ENAME,SAL,DEPTNO FROM EMP ORDER BY sal;ENO EMP.EMPNO%TYPE;

5

EMPNAME EMP.ENAME%TYPE;SAL1 EMP.SAL%TYPE;DNO EMP.DEPTNO%TYPE;

BEGINOPEN C1;

LOOP EXIT WHEN C1%ROWCOUNT=5 OR C1%NOTFOUND;

FETCH C1 INTO ENO,EMPNAME,SAL1,DNO;DBMS_OUTPUT.PUT_LINE('EMPNO ' || ENO ||' EMPNAME ' || EMPNAME ||' SALARY ' || SAL1);

INSERT INTO EMP51 VALUES(ENO,EMPNAME,SAL1,DNO);COMMIT;

END LOOP;CLOSE C1;

END;

B ] IMPLICIT CURSOR

An IMPLICIT cursor is associated with any SQL DML statement that does not have a explicit cursor associated with it.

This includes :" All INSERT statements" All UPDATE statements" All DELETE statements

IMPLICIT CURSOR ATTRIBUTES" SQL%FOUND (Returns true if the DML operation is valid)" SQL%NOTFOUND (Returns true if the DML operation is invalid)" SQL%ROWCOUNT (Returns the no. of rows affected by the DML operation)

SQL%FOUND - IMPLICIT

BEGINUPDATE EMP51 SET SAL=SAL+50.50 WHERE DEPTNO=&Department_No;IF SQL%NOTFOUND THEN

DBMS_OUTPUT.PUT_LINE('Invalid Salary Updation' );ELSif SQL%FOUND THEN

DBMS_OUTPUT.PUT_LINE('Sucessfully Updated' );END IF;

END;

SQL%ROWCOUNT - IMPLICIT

BEGINUPDATE EMP51 SET SAL=SAL+50.50 WHERE DEPTNO=&DNO;IF SQL%NOTFOUND THEN

DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT ||' Rows Sucessfully Updated ' );ELSif SQL%FOUND THEN

DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT ||' Rows Sucessfully Updated ' );END IF;

END;

EXPLCIT CURSOR - UPDATION

DECLARE DNO EMP.DEPTNO%TYPE:=&DEPT_NO; ENO EMP.EMPNO%TYPE; ENAME1 EMP.ENAME%TYPE; ESAL EMP.SAL%TYPE;

6

CURSOR C1 IS SELECT EMPNO,ENAME,SAL FROM EMP WHERE DEPTNO=DNO; BEGIN

OPEN C1; LOOP

FETCH C1 INTO ENO,ENAME1,ESAL; EXIT WHEN C1%NOTFOUND; IF ESAL<1200 THEN UPDATE EMP SET COMM=SAL*.6 WHERE DEPTNO=DNO AND (SAL<1200); ELSIF ESAL>1200 AND ESAL<=1500 THEN UPDATE EMP SET COMM=SAL*.4 WHERE DEPTNO=DNO AND (SAL>1200 AND SAL<=1500); ELSE UPDATE EMP SET COMM=SAL*.5 WHERE DEPTNO=DNO AND (SAL>1500); END IF;

DBMS_OUTPUT.PUT_LINE(ENO); DBMS_OUTPUT.PUT_LINE(ENAME1); END LOOP; COMMIT; DBMS_OUTPUT.PUT_LINE(C1%ROWCOUNT); CLOSE C1;

END;

2 ]DYNAMIC CURSOR

Dynamic Cursor can be used along with DBMS_SQL package .A SQL statement is dynamic, if it is constructed at run time and then executed.

3 ] REF CURSOR

Declaring a cursor variable creates a pointer, not an item. In PL/SQL, a pointer has datatype REF X, where REF is short for REFERENCE and X stands for a class of objects. Therefore, a cursor variable has datatype REF CURSOR.

To execute a multi-row query, Oracle opens an unnamed work area that stores processing information. To access the information, you can use an explicit cursor, which names the work area. Or, you can use a cursor variable, which points to the work area.Mainly, you use cursor variables to pass query result sets between PL/SQL stored subprograms and various clients. Neither PL/SQL nor any of its clients owns a result set; they simply share a pointer to the query work area in which the result set is stored. For example, an OCI client, Oracle Forms application, and Oracle Server can all refer to the same work area.

a] Strong Cursor - Whose return type specified. b] Week Cursor - Whose return type not specified.

Ref CursorRef are the best way of uniqely referring to object instances.It is only supported way of getting at OID ( object identifier ).It is a effecient and light means of passing object information as a information

DrefIt is the 'deference operator.Like VALUE,it return the value of an object,Unlike value.Dref's input is a REF to an column in a table and you want reterive the target instead of the pointer,you DREF.

REF CURSOR - 1

DECLARETYPE RE1 IS REF CURSOR;A RE1;B RE1;A1 NUMBER;

7

B1 VARCHAR2(20);C1 VARCHAR2(20);

BEGINOPEN A FOR SELECT EMPNO,ENAME,JOB FROM EMP;LOOP

FETCH A INTO A1,B1,C1;EXIT WHEN A%NOTFOUND;

DBMS_OUTPUT.PUT_LINE(A1||' '||B1||' '||C1);END LOOP;CLOSE A;

END;/

REF CURSOR - 2

CREATE OR REPLACE PROCEDURE PREF2 ISTYPE RE1 IS REF CURSOR;SQL_STMT RE1;A1 NUMBER;B1 VARCHAR2(20);C1 VARCHAR2(20);

BEGIN DBMS_OUTPUT.PUT_LINE('==========================');

OPEN SQL_STMT FOR SELECT EMPNO,ENAME,JOB FROM EMP;LOOP

FETCH SQL_STMT INTO A1,B1,C1;EXIT WHEN SQL_STMT%NOTFOUND;

DBMS_OUTPUT.PUT_LINE(A1||' '||B1||' '||C1);END LOOP;

----- CLOSE SQL_STMT; DBMS_OUTPUT.PUT_LINE('==========================');

OPEN SQL_STMT FOR SELECT DEPTNO,DNAME,LOC FROM DEPT;LOOP

FETCH SQL_STMT INTO A1,B1,C1;EXIT WHEN SQL_STMT%NOTFOUND;

DBMS_OUTPUT.PUT_LINE(A1||' '||B1||' '||C1);END LOOP;

------- CLOSE SQL_STMT; DBMS_OUTPUT.PUT_LINE('==========================');

OPEN SQL_STMT FOR SELECT LOCID,LOC_NAME,COUNTRY FROM LOCMAST;

DBMS_OUTPUT.PUT_LINE('ID LOCNAME COUNTRY'); DBMS_OUTPUT.PUT_LINE('------------------------------------------------');

LOOPFETCH SQL_STMT INTO A1,B1,C1;EXIT WHEN SQL_STMT%NOTFOUND;

DBMS_OUTPUT.PUT_LINE(A1||' '||B1||' '||C1);END LOOP;

----- CLOSE SQL_STMT;END;/

REF CURSOR - 3 [ With Procedure ]

CREATE OR REPLACE PROCEDURE PREF1(DNO DEPT.DEPTNO%TYPE) ISTYPE RE1 IS REF CURSOR;SQL_STMT RE1;A1 NUMBER;B1 VARCHAR2(20);C1 VARCHAR2(20);

BEGIN

8

DBMS_OUTPUT.PUT_LINE('==========================');OPEN SQL_STMT FOR SELECT DEPTNO,DNAME,LOC FROM DEPT WHERE DEPTNO=DNO;LOOP

FETCH SQL_STMT INTO A1,B1,C1;EXIT WHEN SQL_STMT%NOTFOUND;

DBMS_OUTPUT.PUT_LINE(A1||' '||B1||' '||C1);END LOOP;

------- CLOSE SQL_STMT; DBMS_OUTPUT.PUT_LINE('==========================');

OPEN SQL_STMT FOR SELECT EMPNO,ENAME,JOB FROM EMP WHERE DEPTNO=DNO;LOOP

FETCH SQL_STMT INTO A1,B1,C1;EXIT WHEN SQL_STMT%NOTFOUND;

DBMS_OUTPUT.PUT_LINE(A1||' '||B1||' '||C1);END LOOP;

----- CLOSE SQL_STMT; DBMS_OUTPUT.PUT_LINE('==========================');EXCEPTION

WHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR(-20023,'INVALID DEPARTMENT NUMBER');

END;/

Exec pref1(10);Exec pref1(20);

SUB PROGRAMS

1 ] PROCEDURES

Procedure is a subprogram that contains set of SQL and PL/SQL statements.

MeritsReusability - Subprograms once executed can be used in any number of applicationsMaintainability - Subprogram can simplify maintenance, subprogram will be affected only

its definition changes

Parameter

IN - The IN parameter is used to pass values to a subprogram when it is invokedOUT - The OUT parameter is used to return values to the caller of a subprogramIN OUT The IN OUT parameter is used to pass initial values to the subprogram

when invoked and also it returns updated values to the caller.SYNTAX CREATE OR REPLACE PROCEDURE <PROCEDURE NAME>[PARAM LIST] IS <local declarations> begin executable statement end;

EXAMPLE FOR IN PARAMETER

CREATE OR REPLACE PROCEDURE P1 (ENO IN EMP51.EMPNO%TYPE)IS

BEGINUPDATE EMP51 SET SAL=SAL+SAL*.01 WHERE EMPNO=ENO;

END;

EXAMPLE FOR OUT PARAMETER - SPECIFICATION

CREATE OR REPLACE PROCEDURE P50 (ENO IN EMP51.EMPNO%TYPE, ENAME1 OUT EMP51.ENAME%TYPE) ISBEGIN

SELECT ENAME INTO ENAME1 from emp51 WHERE EMPNO=ENO;

9

Dbms_output.Put_Line(ENAME1); EXCEPTION

WHEN TOO_MANY_ROWS THENDBMS_OUTPUT.PUT_LINE('MORE ROWS');

END;

EXAMPLE FOR OUT PARAMETER – EXECUTION / BODY

SQL> VARIABLE GNAME VARCHAR2(25)SQL> EXECUTE P50(7000,:GNAME);

PROCEDURE - IN OUT - SPECIFICATION

CREATE OR REPLACE PROCEDURE P1002(A1 IN EMP.EMPNO%TYPE,B1 IN OUT EMP.SAL%TYPE) ISC1 NUMBER;BEGIN

SELECT SAL INTO B1 FROM EMP WHERE EMPNO=A1;IF B1<2000 THEN

B1:=B1+200;ELSE

B1:=B1-100;END IF;

EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('NO EMPS' );

END;

PROCEDURE - IN OUT - BODY - IMPLEMENTATIONDECLARE

B NUMBER;A NUMBER:=&AA;

BEGINP1002(A,B);DBMS_OUTPUT.PUT_LINE(B);

END;

Procedure - IN - Exception – Raise Application Error , IMPLICIT CURSOR

CREATE OR REPLACE PROCEDURE P1004(A1 IN DEPT.DEPTNO%TYPE,B1 IN DEPT.DNAME%TYPE) ISBEGIN

UPDATE DEPT SET DNAME=B1 WHERE DEPTNO=A1; DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT); IF SQL%ROWCOUNT=0 THEN

RAISE_APPLICATION_ERROR(-20204,'INVALID UPDATES, TRY AGAIN'); END IF;

END;

EXEC P1004(10,'SALES1');

Procedure - Implicit Cursor - Explicit Cursor for loop -Update

CREATE OR REPLACE PROCEDURE P1007(DNO1 DEPT.DEPTNO%TYPE) ISDNO EMP.DEPTNO%TYPE:=DNO1;CURSOR C1 IS SELECT EMPNO,ENAME,SAL FROM EMP WHERE DEPTNO=DNO;R1 C1%ROWTYPE;

BEGINFOR R1 IN C1LOOP

EXIT WHEN C1%ROWCOUNT>1; UPDATE EMP SET COMM=SAL*.075 WHERE DEPTNO=DNO AND (SAL>1000 AND SAL<=3000);END LOOP;COMMIT;DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT);

END;

10

VIEW SOURCE CODE FOR PROCEDURES

SELECT TEXT FROM USER_SOURCE WHERE NAME='&P1' AND TYPE=’PROCEDURE’

FUNCTIONS

Function is a subprogram that computes and returns a single value.A function is a subprogram that computes a value. Functions and procedures are structured alike, except that functions have a RETURN clause.

FUNCTION NAME [(PARAMETER[, PARAMETER, ...])] RETURN DATATYPE IS[LOCAL DECLARATIONS]BEGIN

EXECUTABLE STATEMENTS[EXCEPTION

EXCEPTION HANDLERS]

A function has two parts: the specification and the body. The function specification begins with the keyword FUNCTION and ends with the RETURN clause, which specifies the datatype of the result value. Parameter declarations are optional. Functions that take no parameters are written without parentheses. The function body begins with the keyword IS and ends with the keyword END followed by an optional function name.

Functions

Advantage

Function is a subprogram that computes and returns a single value.

Reusability

EXAMPLES

Function – Specification

CREATE OR REPLACE FUNCTION F1000(ENO NUMBER) RETURN NUMBER ISESAL EMP.SAL%TYPE;

BEGIN SELECT SAL INTO ESAL FROM EMP WHERE EMPNO=ENO; RETURN ESAL;EXCEPTION

WHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR(-20345,'THIS EMPLOYEE ID NOT EXITST');

END;

Function – Body

DECLAREA NUMBER;BEGINA:=F1000(&EMPNO);DBMS_OUTPUT.PUT_LINE(A);

END;

Function – - SpecificationCREATE OR REPLACE FUNCTION F1001(P_VALUE IN NUMBER) RETURN NUMBER ISBEGIN

RETURN (P_VALUE*0.08);END;

Function – Execution at SQL*Plus

SQL>SELECT EMPNO,ENAME,SAL,COMM,F1001(SAL) FROM EMP WHERE DEPTNO=10;

Benefits of Stored Procedures and Functions

In addition to modularizing application development, stored procedures and functions have the following benefits:

• Improved performance Avoid reparsing for multiple users by exploiting the shared SQL area

11

Avoid PL/SQL parsing at run-time by parsing at compile time Reduce the number of calls to the database and decrease network traffic by bundling commands

• Improved maintenance. Modify routines online without interfering with other users Modify one routine to affect multiple applications Modify one routine to eliminate duplicate testing

• Improved data security and integrity

Control indirect access to database objects from non privileged users with security privileges Ensure that related actions are performed together, or not at all, by funneling activity for related tables

through a single path

Calling Stored Functions from SQL Expressions

SQL expressions can reference PL/SQL user-defined functions. Anywhere a built-in SQL function can be placed, a user-defined function can be placed as well.

Advantages

• Permits calculations that are too complex, awkward, or unavailable with SQL• Increases data independence by processing complex data analysis within the Oracle Server, rather than by retrieving the data into an application• Increases efficiency of queries by performing functions in the query rather than in the application• Manipulates new types of data (for example, latitude and longitude) by encoding character strings and using functions to operate on the strings.

PACKAGE

A package is a schema object that groups logically related PL/SQL types, items, and subprograms. Packages usually have two parts, a specification and a body,

Merits

Simplify security No need to issue GRANT for every procedure in a packageLimit recompilation Change the body of the procedure or function without changing specificationPerformance First call to package loads whole package into memoryInformation Hiding With packages, you can specify which types, items, and subprograms are

public (visible and accessible) or private (hidden and inaccessible).Hiding Implementation details from users, you protect the integrity of the package.

Parts of Package

Parts of Package

PACKAGE SPECIFICATIONThe package specification contains public declarations. The scope of these declarations is local to your database schema and global to the package. So, the declared items are accessible from your application and from anywhere in the package.

THE PACKAGE BODYThe package body implements the package specification. That is, the package body contains the definition of every cursor and subprogram declared in the package specification. Keep in mind that subprograms defined in a package body are accessible outside the package only if their specifications also appear in the package specification.

Example:Specification CREATE OR REPLACE PACKAGE MY_PACK AS PACK_DEPTNO NUMBER(2) := 10; PACK_EMPNO NUMBER(4) := 7369; PROCEDURE MY_PROC(MEMPNO IN NUMBER, MNAME OUT VARCHAR2); FUNCTION MY_FUNC(MDEPTNO IN NUMBER) RETURN NUMBER;

12

PRAGMA RESTRICT_REFERENCES(MY_FUNC,WNDS,WNPS);END MY_PACK;

Body

CREATE OR REPLACE PACKAGE BODY MY_PACK AS PROCEDURE MY_PROC(MEMPNO IN NUMBER, MNAME OUT VARCHAR2) IS BEGIN SELECT ENAME INTO MNAME FROM EMP WHERE EMPNO=MEMPNO; END MY_PROC; FUNCTION MY_FUNC(MDEPTNO IN NUMBER) RETURN NUMBER IS SL NUMBER; BEGIN SELECT SUM(SAL) INTO SL FROM EMP WHERE DEPTNO = MY_PACK.PACK_DEPTNO; RETURN (SL); END MY_FUNC; END MY_PACK;

CREATE OR REPLACE PACKAGE PC1000 ISPROCEDURE P1100 (A1 IN NUMBER);PROCEDURE P1101 (A1 IN NUMBER);END PC1000;/show err

CREATE OR REPLACE PACKAGE BODY PC1000 IS

PROCEDURE P1100 (A1 IN NUMBER) IS ENAME1 EMP.ENAME%TYPE;BEGIN

SELECT ENAME INTO ENAME1 FROM EMP WHERE EMPNO=A1;DBMS_OUTPUT.PUT_LINE (ENAME1);

EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE ('EMPNO NO NOT EXISTS');

END P1100;

PROCEDURE P1101 (A1 IN NUMBER) IS ESAL EMP.SAL%TYPE;

BEGINSELECT SAL INTO ESAL FROM EMP WHERE EMPNO=A1;DBMS_OUTPUT.PUT_LINE (ESAL);

EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE ('EMPNO NO NOT EXISTS');

END P1101;

END PC1000;

/show err

CREATE PACKAGE PC1000 ISPROCEDURE P1100 (A1 IN NUMBER);

END PC1000;/show err

-------------------------------------------------

CREATE OR REPLACE PACKAGE PC1003 ISFUNCTION F1103(Z1 IN NUMBER) RETURN NUMBER;FUNCTION F1104(Z1 IN NUMBER) RETURN varchar2;

13

END PC1003;

CREATE OR REPLACE PACKAGE BODY PC1003 ISFUNCTION F1103(Z1 IN NUMBER) RETURN NUMBER ISEXP1 EMP.SAL%TYPE;

BEGINSELECT (SYSDATE-HIREDATE)/365 INTO EXP1 FROM EMP WHERE EMPNO=Z1;RETURN EXP1;

END F1103;

FUNCTION F1104(Z1 IN NUMBER) RETURN varchar2 ISEXP1 EMP.ename%TYPE;

BEGINSELECT ename INTO EXP1 FROM EMP WHERE EMPNO=Z1;RETURN EXP1;

END F1104;END PC1003;/show err

--------------------------------------------------------------------------------

DECLAREA2 NUMBER;

BEGINA2:=PC1003.F1103(&EMPNO);DBMS_OUTPUT.PUT_LINE(A2);

EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('EMP NOS NONE');

END;

DECLAREA2 varchar2(25);

BEGINA2:=PC1003.F1104(&EMPNO);DBMS_OUTPUT.PUT_LINE(A2);

EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('EMP NOS NONE');

END;

CREATE OR REPLACE PACKAGE PC1000 ISPROCEDURE P1101 (A1 IN NUMBER);FUNCTION F1101(Z1 IN NUMBER) RETURN varchar2;

END PC1000;/show err

CREATE OR REPLACE PACKAGE BODY PC1000 ISPROCEDURE P1101 (A1 IN NUMBER) IS ESAL EMP.SAL%TYPE;

BEGINSELECT SAL INTO ESAL FROM EMP WHERE EMPNO=A1;DBMS_OUTPUT.PUT_LINE (ESAL);

EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE ('EMPNO NO NOT EXISTS');

END P1101;

FUNCTION F1101(Z1 IN NUMBER) RETURN VARCHAR2 ISEXP1 EMP.ENAME%TYPE;

BEGINSELECT ENAME INTO EXP1 FROM EMP WHERE EMPNO=Z1;RETURN EXP1;

EXCEPTIONWHEN NO_DATA_FOUND THEN

14

DBMS_OUTPUT.PUT_LINE ('EMPNO NO NOT EXISTS');

END F1101;END PC1000;/SHOW ERR

DECLAREA2 VARCHAR2(25);

BEGINA2:=PC1000.F1101(&EMPNO);DBMS_OUTPUT.PUT_LINE(A2);

EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('EMP NOS NONE');

END;

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

CREATE OR REPLACE PACKAGE PC1 IS PROCEDURE <PROC NAME>; FUNCTION <FUN NAME> RETURN NUMBER;END PC1

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

CREATE OR REPLACE PACKAGE PC1106 ISPROCEDURE P1106(dno dept.deptno%type);

END PC1106;

--------------------------

CREATE OR REPLACE PACKAGE BODY PC1106 IS

PROCEDURE P1106(dno dept.deptno%type) ISCURSOR C1 IS SELECT EMPNO,ENAME,(SYSDATE-HIREDATE)/365 SERVICE FROM EMP where deptno=dno ;

ENO1 NUMBER;ENAME1 VARCHAR2(25);EXP1 NUMBER;

BEGINOPEN C1;LOOP FETCH C1 INTO ENO1,ENAME1,EXP1; EXIT WHEN C1%NOTFOUND; DBMS_OUTPUT.PUT_LINE(ENO1||' '||ENAME1||' '||ROUND(EXP1,2) );END LOOP;

CLOSE C1; END P1106;

END PC1106;/

show errCOMPARING PROCEDURES AND FUNCTIONS

Procedure Function

Execute as a PL/SQL statement Invoke as part of an expression

No RETURN datatype Must contain a RETURN datatype

Can return none, one or many values Must return a single value

Benefits of Sub Programs (Stored Procedures and Functions)

Improved performance, improved maintenance, improved data security and integrity15

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_EMP’ ORDER BY LINE;

COMPILATION ERRORS USING USER_ERRORS

To obtain the text for compile errors, use the USER_ERRORS data dictionary view or the SHOW ERRORS SQL*Plus command.

Also examine the ALL_ERRORS and DBA_ERRORS views, each of which contains the additional column OWNER, for the owner of the object.

List Compilation Errors Using SHOW ERRORS

Use SHOW ERRORS without any arguments at the SQL prompt to obtain compilation errors for the last object you compiled.

DESCRIBING PROCEDURES AND FUNCTIONS

To display a procedure or function and its parameter list, use the DESCRIBE SQL*Plus command.

PACKAGE OVERLOADING

PL/SQL allows two or more packaged subprograms to have the same name. This option is useful when you want a subprogram to accept parameters that have different datatypes. For example, the following package defines two procedures named journalize:

CREATE PACKAGE JOURNAL_ENTRIES ASPROCEDURE JOURNALIZE (AMOUNT NUMBER, TRANS_DATE VARCHAR2);PROCEDURE JOURNALIZE (AMOUNT NUMBER, TRANS_DATE NUMBER );

END JOURNAL_ENTRIES;

CREATE PACKAGE BODY JOURNAL_ENTRIES ASPROCEDURE JOURNALIZE (AMOUNT NUMBER, TRANS_DATE VARCHAR2) IS

BEGININSERT INTO JOURNAL VALUES (AMOUNT, TO_DATE(TRANS_DATE, ’DD-MON-YYYY’));

END JOURNALIZE;

PROCEDURE JOURNALIZE (AMOUNT NUMBER, TRANS_DATE NUMBER) ISBEGIN

INSERT INTO JOURNAL VALUES (AMOUNT, TO_DATE(TRANS_DATE, ’J’));END JOURNALIZE;

END JOURNAL_ENTRIES;The first procedure accepts trans_date as a character string, while the second procedure accepts it as a number (the Julian day). Yet, each procedure handles the data appropriately.

CURSOR – Cotn…………

OTHER CURSORS

1 ] DYNAMIC CURSOR

Dynamic Cursor can be used along with DBMS_SQL package .A SQL statement is dynamic, if it is constructed at run time and then executed.

2 ] REF CURSOR

16

To execute a multi-row query, Oracle opens an unnamed work area that stores processing information. To access the information, you can use an explicit cursor, which names the work area. Or, you can use a cursor variable, which points to the work area.

Mainly, you use cursor variables to pass query result sets between PL/SQL stored subprograms and various clients. Neither PL/SQL nor any of its clients owns a result set; they simply share a pointer to the query work area in which the result set is stored. For example, an OCI client, Oracle Forms application, and Oracle Server can all refer to the same work area.

Ref are the best way of uniqely referring to object instances.It is only supported way of getting at OID ( object identifier ).It is a effecient and light means of passing object information as a information

a] Strong Cursor - Whose return type specified. b] Week Cursor - Whose return type not specified.

Declaring a cursor variable creates a pointer, not an item. In PL/SQL, a pointer has datatype REF X, where REF is short for REFERENCE and X stands for a class of objects. Therefore, a cursor variable has datatype REF CURSOR.

DREF

It is the 'deference operator. Like VALUE, it returns the value of an object, Unlike value.Dref's input is a REF to an column in a table and you want retrieve the target instead of the pointer, you DREF.

CURSOR SUBQUERY

• The cursor sub query opens a nested cursor for each evaluation of the cursor expression.• For each row of the parent query, it returns a cursor in the SELECT list corresponding to the cursor expression.• Fetches have to be performed to retrieve the results of a sub query.

CURSOR SUBQUERY IN REF CURSOR: EXAMPLE

DECLARETYPE refcursortype IS REF CURSOR;n NUMBER;emprow employees%rowtype;empcur1 refcursortype;empcur2 refcursortype;

BEGINOPEN empcur1 FORSELECT cursor(SELECT * FROM employees)FROM departments;FETCH empcur1 INTO empcur2;FETCH empcur2 INTO emprow;CLOSE empcur1;

END;

CURSOR SUBQUERY IN EXPLICIT CURSOR: EXAMPLE

DECLARETYPE REFCURSORTYPE IS REF CURSOR;EMPCUR1 REFCURSORTYPE;CURSOR C1 IS SELECT DEPARTMENT_NAME,CURSOR(SELECT EMPLOYEE_ID FROM EMPLOYEES E WHERE E.DEPARTMENT_ID=D.DEPARTMENT_ID)FROM DEPARTMENTS D;EMPROW EMPLOYEES%ROWTYPE;

V_DNAME DEPARTMENTS.DEPARTMENT_NAME%TYPE;BEGIN

OPEN C1;LOOP

FETCH C1 INTO V_DNAME,EMPCUR1;FETCH EMPCUR1 INTO EMPROW;

…END LOOP;CLOSE C1;

END;

17

CURSOR SUBQUERY: NESTED CURSOR ATTRIBUTES

• A nested cursor is prepared the first time an operation is performed on it.• Resources are released after all the nested cursors associated with this cursor have been prepared.• The parent is checked at each preparation to verify if this is the last nested cursor so that resources can be released.

REF CURSOR

If any normal cursor is declared, we have to give a select statement for that. For example Cursor C_cur is select * from emp;

If you call the cursor C_cur anywhere or anytime, it will execute only this select statement .ie it is meant for the Select * from emp; If you want to execute multiple select statements, we have to declare multiple cursors. It will be cumbersome. So, if there is a single cursor which can open multiple select statements, then it will be easy for the programmer.

There are two steps to handle the ref cursor.

1. declaring a ref cursor 2. declaring a variable of the cursor.

The ref cursor can be declared in PL/SQL block, Subprograms and Packages.

Example:

DECLARETYPE C_REF IS REF CURSOR; /*DECLARING REF CURSOR NAMED C_REF */C_VAR1 C_REF; /*DECLARING TWO CURSOR VARIABLES NAMED

C_VAR1 AND C_VAR2 OF REF CURSOR C_REF*/C_VAR2 C_REF;A NUMBER;B VARCHAR2(20);C VARCHAR2(20);

BEGINOPEN C_VAR1 FOR SELECT EMPNO,ENAME,JOB FROM EMP; /*- STATEMENT1*/LOOP

FETCH C_VAR1 INTO A,B,C;EXIT WHEN C_VAR1%NOTFOUND;DBMS_OUTPUT.PUT_LINE(A||' '|| B||' '||C ); /*-

DISPLAYS THE EMPNO,ENAME,JOB*/END LOOP;CLOSE C_VAR1;

OPEN C_VAR2 FOR SELECT DEPTNO,DNAME,LOC FROM DEPT; /*-STATEMENT2*/LOOP

FETCH C_VAR2 INTO A,B,C;EXIT WHEN C_VAR2%NOTFOUND;DBMS_OUTPUT.PUT_LINE(A||' '|| B||' '||C ); /*- DIPLAYS

THE DEPTNO,DNAME,LOC*/END LOOP;CLOSE C_VAR2;

END;

Thus, with single ref cursor, we can declare any number of cursor variables and each variable can be used for different select statements.

DATABASE TRIGGERS

A Trigger defines an action the database should take when some database related event occurs. Triggers may be used to supplement declarative referential integrity, to enforce complex business rules.

A database trigger is a stored subprogram associated with a table. You can have Oracle automatically fire the trigger before or after an INSERT, UPDATE, or DELETE statement affects the table.

18

Triggers are executed when a specific data manipulation command are performed on specific tables

ROW LEVEL TRIGGERS

Row Level triggers execute once for each row in a transaction. Row level triggers are create using FOR EACH ROW clause in the create trigger command.

STATEMENT LEVEL TRIGGERS

Statement Level triggers execute once for each transaction. For example if you insert 100 rows in a single transaction then statement level trigger will be executed once.

BEFORE and AFTER Triggers

Since triggers occur because of events, they may be set to occur immediately before or after those events.

The following table shows the number of triggers that you can have for a table. The number of triggers you can have a for a table is 14 triggers.

The following table shows the number of triggers that you can have for a table. The number of triggers you can have a for a table is 14 triggers.

ROW LEVEL TRIGGER STATEMENT LEVEL TRIGGER

BEFORE INSERT

UPDATE

DELETE

INSERT

UPDATE

DELETE

INSTEAD OF INSTEAD OF ROW

AFTER INSERT

UPDATE

DELETE

INSERT

UPDATE

DELETE

ADVANTAGES OF TRIGGERS Feature Enhancement

Security The Oracle Server allows table access to users or roles. Triggers allow table access according to data values.

Auditing The Oracle Server tracks data operations on tables. Triggers track values for data operations on tables.

Data integrity The Oracle Server enforces integrity constraints. Triggers implement complex integrity rules.

Referential integrity The Oracle Server enforces standard referential integrity rules. Triggers implement nonstandard functionality.

Table replication The Oracle Server copies tables asynchronously into snapshots. Triggers copy tables Synchronously into replicas.

Derived data The Oracle Server computes derived data values manually. Triggers compute derived data values automatically.

Event logging The Oracle Server logs events explicitly. Triggers log events transparently.

19

Syntax:

CREATE OR REPLACE TRIGGER <TRIGGER NAME> [ BEFORE | AFTER | INSTEAD OF ]

(INSERT OR UPDATE OR DELETE) ON <TABLE NAME> REFERENCING OLD AS OLD | NEW AS NEW FOR EACH ROW

BEGIN

END;

Example 1:

CREATE OR REPLACE TRIGGER MY_TRIG BEFORE INSERT OR UPDATE OR DELETE ON

DETAIL FOR EACH ROW

BEGIN

IF LTRIM(RTRIM(TO_CHAR(SYSDATE,'DAY')))='FRIDAY' THEN

IF INSERTING THEN

RAISE_APPLICATION_ERROR(-20001,'INSERT IS NOT POSSIBLE');

ELSIF UPDATING THEN

RAISE_APPLICATION_ERROR(-20001,'UPDATE IS NOT POSSIBLE');

ELSIF DELETING THEN

RAISE_APPLICATION_ERROR(-20001,'DELETE IS NOT POSSIBLE');

END IF;

END IF;

END;

Example 2:

CREATE OR REPLACE TRIGGER MY_TRIG AFTER INSERT ON

ITEM FOR EACH ROW

DECLARE

MITEMID NUMBER;

MQTY NUMBER;

BEGIN

SELECT ITEMID INTO MITEMID FROM STOCK WHERE ITEMID = :NEW.ITEMID;

UPDATE STOCK SET QTY=QTY+:NEW.QTY WHERE ITEMID=:NEW.ITEMID;

EXCEPTION WHEN NO_DATA_FOUND THEN

INSERT INTO STOCK VALUES (:NEW.ITEMID, :NEW.QTY);

END;

Example 3:

CREATE OR REPLACE TRIGGER MY_TRIG AFTER DELETE ON

EMP FOR EACH ROW

BEGIN

INSERT INTO EMP_BACK VALUES (:OLD.EMPNO, :OLD.ENAME, :OLD.SAL, :OLD.DEPTNO);

END;

Example 4:

20

CREATE OR REPLACE TRIGGER TR02 BEFORE INSERT OR UPDATE OR DELETE ON EMP100DECLARE

D1 VARCHAR(3);BEGIN

D1:=TO_CHAR(SYSDATE,'DY');

IF D1 IN('TUE','MON') THEN RAISE_APPLICATION_ERROR(-20025,'TRY ON ANOTHER DAY');

END IF;END;

Example 5:

CREATE OR REPLACE TRIGGER TR01 AFTER DELETE ON DEPT200 FOR EACH ROWBEGIN

INSERT INTO DEPT1 VALUES (:OLD.DEPTNO,:OLD.DNAME,:OLD.LOC);END;/SHOW ERR

Example 6:

CREATE OR REPLACE TRIGGER TR03 AFTER UPDATE ON EMP FOR EACH ROWBEGIN

UPDATE EMP100 SET SAL=:OLD.SAL*2 WHERE EMPNO=:OLD.EMPNO;END;/SHOW ERR

Example 7:

CREATE OR REPLACE TRIGGER TR05 AFTER UPDATE ON EMP100DECLARE

U1 VARCHAR2(50);BEGIN

SELECT USER INTO U1 FROM DUAL;INSERT INTO USER1 VALUES(U1,SYSDATE,'UPDATE');

END;/SHOW ERR

Example 8:

CREATE OR REPLACE TRIGGER TR06 AFTER DELETE ON EMP100DECLAREU1 VARCHAR2(50);BEGINSELECT USER INTO U1 FROM DUAL;INSERT INTO USER1 VALUES(U1,SYSDATE,'DELETE');END;/SHOW ERR

PL/SQL RECORD

A record is a group of related data items stored in fields, each with its own name and datatype. A record containing a field for each item lets you treat the data as a logical unit. Thus, records make it easier to organize and represent information.

Suppose you have various data about an employee such as name, salary,and hire date. These items are logically related but dissimilar in type. A record containing a field for each item lets you treat the data as a logical unit. Thus, records make it easier to organize and represent information.

The attribute %ROWTYPE lets you declare a record that represents a row in a database table. However, you cannot specify the datatypes of fields in the record or declare fields of your own. The datatype RECORD lifts those restrictions and lets you define your own records.

21

There are two steps to declare a record.

1. Declaring a record and 2. Declaring a variable of the record.

DECLARE

TYPE EMP_REC IS RECORD ( A NUMBER(4), B VARCHAR2(30), C NUMBER(10,2));TYPE DEPT_REC IS RECORD ( A NUMBER(2), B VARCHAR2(30), C VARCHAR2(30));

/* DECLARING RECORD TYPE*/

REC_VAR1 EMP_REC; /*- DECLARING VARIABLE OF RECORD TYPE*/

REC_VAR2 DEPT_REC;

BEGIN

SELECT EMPNO,ENAME,SAL INTO REC_VAR1 FROM EMP WHERE EMPNO = 7788;SELECT DEPTNO,DNAME,LOC INTO REC_VAR2 FROM DEPT WHERE DEPTNO = 10;

/* FETCH COLUMN VALUES AND STORE IN THE RECORD VARIABLE*/

DBMS_OUTPUT.PUT_LINE(REC_VAR1.A); -- DISPLAYS THE EMPNODBMS_OUTPUT.PUT_LINE(REC_VAR1.B); -- DISPLAYS THE ENAMEDBMS_OUTPUT.PUT_LINE(REC_VAR1.C); -- DISPLAYS THE SALDBMS_OUTPUT.PUT_LINE(REC_VAR2.A); -- DISPLAYS THE NAME OF THE

DEPARTMENTDBMS_OUTPUT.PUT_LINE(REC_VAR2.B); -- DISPLAYS THE NAME OF THE

DEPARTMENTDBMS_OUTPUT.PUT_LINE(REC_VAR2.C); -- DISPLAYS THE NAME OF THE

LOCATIONEND;

We can't store the record type in the database. We can declare the record type in pl/sql block, subprograms and package.

DECLARE TYPE R1 IS RECORD(EMPNO NUMBER(5),

ENAME VARCHAR2(10), HIREDATE DATE);

R2 R1;BEGIN

SELECT EMPNO,ENAME,HIREDATE INTO R2 FROM EMP WHERE EMPNO=&ASK_EMPNO;DBMS_OUTPUT.PUT_LINE(R2.EMPNO||' '||R2.ENAME||' '||R2.HIREDATE);

EXCEPTIONWHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR(-20023,'INVALID EMPLOYEE NUMBER');

END;

WITH PROCEDURE

SET SERVEROUT ON;CREATE OR REPLACE PROCEDURE PR_PLRECORD (ENO EMP.EMPNO%TYPE) IS TYPE R1 IS RECORD(EMPNO NUMBER(5),

ENAME VARCHAR2(10), HIREDATE DATE);

R2 R1;BEGIN

SELECT EMPNO,ENAME,HIREDATE INTO R2 FROM EMP WHERE EMPNO=ENO;

22

DBMS_OUTPUT.PUT_LINE(R2.EMPNO||' '||R2.ENAME||' '||R2.HIREDATE);EXCEPTION

WHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR(-20023,'INVALID EMPLOYEE NUMBER');

END;

--------------------------------------------------------------------------------------------

WITH CURSOR / PROCEDURE

SET SERVEROUT ON;CREATE OR REPLACE PROCEDURE PR1 (DNO EMP.DEPTNO%TYPE) IS TYPE R1 IS RECORD(EMPNO NUMBER(5),

ENAME VARCHAR2(10), HIREDATE DATE);

R2 R1; CURSOR C1 IS

SELECT EMPNO,ENAME,HIREDATE FROM EMP WHERE DEPTNO=DNO;BEGIN OPEN C1; LOOP

EXIT WHEN C1%NOTFOUND;FETCH C1 INTO R2;

DBMS_OUTPUT.PUT_LINE(R2.EMPNO||' '||R2.ENAME||' '||R2.HIREDATE); END LOOP; CLOSE C1;EXCEPTION

WHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR(-20023,'INVALID DEPARTMENT NUMBER');

END;/SHOW ERR--------------------------------------------------------------------------------------------

WITH CURSOR / PROCEDURE -- JOINS

SET SERVEROUT ON;CREATE OR REPLACE PROCEDURE PR2 (DNO EMP.DEPTNO%TYPE) IS TYPE R1 IS RECORD(EMPNO NUMBER(5),

ENAME VARCHAR2(10), HIREDATE DATE, LOC DEPT.LOC%TYPE);

R2 R1; CURSOR C1 IS

SELECT EMPNO,ENAME,HIREDATE,LOC FROM EMP,DEPT WHERE EMP.DEPTNO=DNO AND DEPT.DEPTNO=EMP.DEPTNO;BEGIN OPEN C1; LOOP

EXIT WHEN C1%NOTFOUND;FETCH C1 INTO R2;

DBMS_OUTPUT.PUT_LINE(R2.EMPNO||' '||R2.ENAME||' '||R2.HIREDATE||' '||R2.LOC); END LOOP; CLOSE C1; EXCEPTION

WHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR(-20023,'INVALID DEPARTMENT NUMBER');

END;/SHOW ERR

23

PL/SQL TABLES

PL/SQL tables are temporary array like objects used in a PL/SQL block. The column data type can belong to any scalar data type.

PL/SQL TABLE EXAMPLE

PL/SQL TABLE - 1

SET SERVEROUT ON;DECLARE

TYPE R1 IS TABLE OF EMP.ENAME%TYPE INDEX BY BINARY_INTEGER;R2 R1;I BINARY_INTEGER:=0;

BEGIN FOR R3 IN (SELECT ENAME FROM EMP) LOOP

I:=I+1; R2(I):=R3.ENAME; DBMS_OUTPUT.PUT_LINE(R2(I)); END LOOP;END;/SHOW ERR --------------------------------------------------------------------------------------------PL/SQL TABLE - 2

DECLARETYPE R1 IS TABLE OF DEPT%ROWTYPE INDEX BY BINARY_INTEGER;R2 R1;

BEGINFOR I IN 1..10LOOP

SELECT * INTO R2(I) FROM DEPT WHERE DEPTNO=10; DBMS_OUTPUT.PUT_LINE(R2(I).DNAME ||' '||R2(I).LOC||' '||R2(I).DEPTNO);

END LOOP;EXCEPTION

WHEN TOO_MANY_ROWS THENRAISE_APPLICATION_ERROR(-20023,'MORE THAN ONE ROWS');

END;/=========================

PL/SQL TABLE - 2A

DECLARETYPE R1 IS TABLE OF DEPT%ROWTYPE INDEX BY BINARY_INTEGER;CURSOR C1 IS SELECT * FROM DEPT;R2 R1;I BINARY_INTEGER:=0;DNAME VARCHAR2(25);

BEGINFOR A IN C1LOOP

I:=I+1;DBMS_OUTPUT.PUT_LINE((I)||' '||A.DEPTNO||' '||A.DNAME||' '||

A.LOC);DNAME:=A.DNAME;DBMS_OUTPUT.PUT_LINE(DNAME);

END LOOP;EXCEPTION

WHEN TOO_MANY_ROWS THENRAISE_APPLICATION_ERROR(-20023,'MORE THAN ONE ROWS');

END;

24

PL/SQL TABLE - 3

DECLARETYPE R1 IS TABLE OF EMP.ENAME%TYPE INDEX BY BINARY_INTEGER;R2 R1;CURSOR C1 IS SELECT ENAME FROM EMP;I BINARY_INTEGER:=0;

BEGINFOR A IN C1LOOP I:=I+1; R2(I):=A.ENAME; DBMS_OUTPUT.PUT_LINE(R2(I));END LOOP;

END;/

PL/SQL TABLE - 4

SET SERVEROUT ON;CREATE OR REPLACE PROCEDURE PR_PL1 (DNO EMP.DEPTNO%TYPE) IS

TYPE R1 IS TABLE OF EMP.ENAME%TYPE INDEX BY BINARY_INTEGER;R2 R1;I BINARY_INTEGER:=0;

BEGIN FOR R3 IN (SELECT ENAME FROM EMP WHERE DEPTNO=DNO) LOOP

I:=I+1; R2(I):=R3.ENAME;-- DBMS_OUTPUT.PUT_LINE(R2(I)); DBMS_OUTPUT.PUT_LINE('MR. '||R2(I)); END LOOP;EXCEPTION

WHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR(-20023,'INVALID DEPARTMENT NUMBER');

END;/

EXEC PR_PL1(20);EXEC PR_PL1(30);

Trigger Cotn……….. < SYSTEM LEVEL TRIGGERS >

LOGON and LOGOFF Trigger Example You can create this trigger to monitor how often you log on and off, or you may want to write a report on how long you are logged on for. If you were a DBA wanting to do this, you would replace SCHEMA with DATABASE.

1. CREATE OR REPLACE TRIGGER LOGON_TRIGAFTER logon ON SCHEMABEGIN

INSERT INTO log_trig_table 5 (user_id, log_date, action) VALUES (user, sysdate, ’Logging on’);

END;

2. CREATE OR REPLACE TRIGGER LOGOFF_TRIGBEFORE logoff ON SCHEMABEGIN

INSERT INTO log_trig_table (user_id, log_date, action) VALUES (user, sysdate, ’Logging off’);

END;

CALL STATEMENT This allows you to call a stored procedure, rather than coding the PL/SQL body in the trigger itself.

25

CREATE [OR REPLACE] TRIGGER trigger_name timingevent1 [OR event2 OR event3]ON table_name[REFERENCING OLD AS old | NEW AS new][FOR EACH ROW][WHEN condition]CALL procedure_name

CREATE TRIGGER TEST3BEFORE INSERT ON EMPCALL LOG_EXECUTION

ORACLE SUPPLIED PACKAGES

• Provided with the Oracle Server• Extend the functionality of the database• Allow access to certain SQL features normally restricted for PL/SQL

DYNAMIC SQL:

Static SQL Statement:

Most PL/SQL programs do a specific, predictable job. For example, a stored procedure might accept an employee number and salary increase, then update the sal column in the emp table. In this case, the full text of the UPDATE statement is known at compile time. Such statements do not change from execution to execution. So, they are called static SQL statements.

Dynamic SQL Statement:

However, some programs must build and process a variety of SQL statements at run time. For example, a general-purpose report writer must build different SELECT statements for the various reports it generates. In this case, the full text of the statement is unknown until run time. Such statements can, and probably will, change from execution to execution. So, they are called dynamic SQL statements.

Dynamic SQL statements are stored in character strings built by your program at run time. Such strings must contain the text of a valid SQL statement or PL/SQL block. They can also contain placeholders for bind arguments. A placeholder is an undeclared identifier, so its name, to which you must prefix a colon, does not matter.

DYNAMIC SQL

• Is a SQL statement stored as character string• Allows general purpose code to be written • Allows DDL statements to be written and executed from PL/SQL• Is written using DBMS_SQL, EXECUTE IMMEDIATE or OPEN-FOR/FETCH/CLOSE

Execute Immediate: To process most dynamic SQL statements, you use the EXECUTE IMMEDIATE Statement.

USING DDL AND DYNAMIC SQL

CREATE OR REPLACE PROCEDURE DROP_TABLE (TABLE_NAME IN VARCHAR2) AS CID INTEGER;

BEGIN

/* OPEN NEW CURSOR AND RETURN CURSOR ID. */ CID := DBMS_SQL.OPEN_CURSOR; /* PARSE AND IMMEDIATELY EXECUTE DYNAMIC SQL STATEMENT BUILT BY CONCATENATING TABLE NAME TO DROP TABLE COMMAND. */

26

DBMS_SQL.PARSE(CID, 'DROP TABLE ' || TABLE_NAME, DBMS_SQL.V7); /* CLOSE CURSOR. */ DBMS_SQL.CLOSE_CURSOR(CID);

EXCEPTION /* IF AN EXCEPTION IS RAISED, CLOSE CURSOR BEFORE EXITING. */ WHEN OTHERS THEN DBMS_SQL.CLOSE_CURSOR(CID); RAISE; -- RERAISE THE EXCEPTION

END DROP_TABLE;

COMPOSITE DATA TYPE

PL/SQL RECORD

A PL/SQL Record is a collection of individual fields that represent a row in a table. By using records we can group the data into one structure and then manipulate this structure as one entity r logical unit.

27

A record is a group of related data items stored in fields, each with its own name and data type. A record containing a field for each item lets you treat the data as a logical unit. Thus, records make it easier to organize and represent information.

Suppose you have various data about an employee such as name, salary, and hire date. These items are logically related but dissimilar in type. A record containing a field for each item lets you treat the data as a logical unit. Thus, records make it easier to organize and represent information.

The attribute %ROWTYPE lets you declare a record that represents a row in a database table. However, you cannot specify the datatypes of fields in the record or declare fields of your own. The datatype RECORD lifts those restrictions and lets you define your own records.

There are two steps to declare a record.

1. Declaring a record and 2. Declaring a variable of the record.

declaretype emp_rec is record ( a number(4), b varchar2(30), c number(10,2));type dept_rec is record ( a number(2), b varchar2(30), c varchar2(30));

/* declaring record type*/rec_var1 emp_rec; /*- declaring variable of record type*/rec_var2 dept_rec;

beginselect empno,ename,sal into rec_var1 from emp where empno = 7788;select deptno,dname,loc into rec_var2 from dept where deptno = 10;/* fetch column values and store in the record variable*/dbms_output.put_line(rec_var1.a); -- displays the empnodbms_output.put_line(rec_var1.b); -- displays the enamedbms_output.put_line(rec_var1.c); -- displays the saldbms_output.put_line(rec_var2.a); -- displays the name of the departmentdbms_output.put_line(rec_var2.b); -- displays the name of the departmentdbms_output.put_line(rec_var2.c); -- displays the name of the location

end;

We can't store the record type in the database. We can declare the record type in pl/sql block, subprograms and package.

PL /SQL RECORD -1

Declare Type r1 is record(empno number(5),

ename varchar2(10), hiredate date);

r2 r1;Begin

select empno,ename,hiredate into r2 from emp where empno=&Ask_Empno;dbms_output.put_line(r2.empno||' '||r2.ename||' '||r2.hiredate);

Exceptionwhen no_data_found thenraise_application_error(-20023,'Invalid Employee Number');

End;

With Procedure – PL/SQL RECORD - 2

set serverout on;create or replace procedure pr_plrecord (eno emp.empno%type) is Type r1 is record(empno number(5),

ename varchar2(10), hiredate date);

r2 r1;Begin

Select empno,ename,hiredate into r2

28

from emp where empno=eno;

dbms_output.put_line(r2.empno||' '||r2.ename||' '||r2.hiredate);Exception

when no_data_found thenraise_application_error(-20023,'Invalid Employee Number');

End;

PL/SQL TABLES

PL/SQL tables are temporary array like objects used in a PL/SQL block. The column data type can belong to any scalar data type.

PL/SQL TABLE - 1

set serverout on;Declare

Type r1 is table of emp.ename%type index by binary_integer;r2 r1;i binary_integer:=0;

Begin For r3 in (Select ename from emp) Loop

i:=i+1; r2(i):=r3.ename; dbms_output.put_line(r2(i)); End Loop;End;/show err PL/SQL TABLE - 2

DeclareType r1 is table of dept%rowtype index by Binary_Integer;r2 r1;

Beginfor i in 1..10Loop

select * into r2(i) from dept where deptno=10; dbms_output.put_line(r2(i).dname ||' '||r2(i).loc||' '||r2(i).deptno);End Loop;

ExceptionWhen Too_many_rows Then

Raise_Application_Error(-20023,'More than one rows');End;

ORACLE 9I

Advanced Explicit Cursor Concepts

1. FOR UPDATE WAIT Clause

Lock the rows before the update or delete. Use explicit locking to deny access for the duration of a transaction.

Syntax

Cursor eipc1 is select * from emp for update [ of column_reference ] [ NOWAIT ]

Column Reference It is column in the table against which the query is performed

29

[ A list of column may also be used ]

NOWAIT Returns an Oracle Error if the rows are locked by another session.

• The SELECT... FOR UPDATE statement has been modified to allow the user to specify how long the command should wait if the rows being selected are locked.

• If NOWAIT is specified, then an error is returned immediately if the lock cannot be obtained.

Example of Using FOR UPDATE WAIT Clause

1. SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = 10 FOR UPDATE WAIT 20;

2. DECLARECURSOR EMP_CURSOR IS SELECT EMPNO, ENAME, DNAME FROM EMP,DEPT WHERE EMP.DEPTNO=DEPT.DEPTNO AND EMP.DEPTNONO=80FOR UPDATE OF SALARY NOWAIT;

[ Retrieve the Employees who work in department 80 and update their Salary ]

2. The WHERE CURRENT OF Clause

Use cursors to update or delete the cursor row. Include the FOR UPDATE clause in the cursor query to lock the row first. Use the WHERE CURRENT OF clause to refer the current row from an explicit cursor.

SyntaxWHERE CURRENT OF < cursor_name >

Cursor_Name -It is the name of a declared cursor. [ The cursor have been declared with the FOR UPDATE clause]

Example of Using FOR WHERE CURRENT OF Clause1. DECLARE

CURSOR EMP_CURSOR IS SELECT EMPNO, ENAME, DNAME FROM E.EMP,D.DEPT WHERE EMP.DEPTNO=DEPT.DEPTNO AND EMP.DEPTNONO=80 FOR UPDATE OF SALARY NOWAIT;

BEGINFOR I IN EMP_CURSOR;LOOP

IF I.SAL<5000 THEN

UPDATE EMP SET SALARY=I.SAL*1.10 WHERE CURRENT OF EMP_CURSOR;

END IF;END LOOP;

END;

[ The Example loops through each employee in department 80 , and checks whether the salary is less than 5000.If salary is less than , the salary is raised by 10%. The where current of clause in the UPDATE statement refers to the currently fetched records. ]

3. CURSORS WITH SUB QUERIES

Sub queries are often used in the WHERE clause of select statement. It can be used to FROM clause, creating a temporary data source for the query.

EXCEPTION

In PL/SQL, a warning or error condition is called an exception. Predefined exceptions are error conditions that are defined by the Oracle server. No predefined exceptions are any other standard Oracle Server Error. User defined exceptions are exception specific to your application.

DECLARE

30

TYPE REFCURSORTYPE IS REF CURSOR;EMPCUR1 REFCURSORTYPE;CURSOR C1 IS SELECT DEPARTMENT_NAME,CURSOR(SELECT EMPLOYEE_ID FROM EMPLOYEES E WHERE E.DEPARTMENT_ID =D.DEPARTMENT_ID)FROM DEPARTMENTS D;EMPROW EMPLOYEES%ROWTYPE;V_DNAME DEPARTMENTS.DEPARTMENT_NAME%TYPE;

BEGINOPEN C1;

LOOPFETCH C1 INTO V_DNAME,EMPCUR1;FETCH EMPCUR1 INTO EMPROW;…

END LOOP;CLOSE C1;

END;

31