13 PL/SQL COMS20700 Databases Dr. Essam Ghadafi
PL/SQL - OVERVIEW PL/SQL: Procedure Language/Structured Query Language. Provides programming languages features: IF, Loops, subroutines,... Code can be compiled and stored in the database. Compiled subroutines can be called from SQL. In Oracle, an interface called SQL*PLUS is used for SQL, PL/SQL.
PL/SQL - ANONYMOUS BLOCKS [Declare /* The Declaration Section */ ] BEGIN /* The Executable Section - Required */ [EXCEPTION /* The Exception Section */ ] END; / We add the symbol / to execute the code.
VARIABLE DECLARATION Syntax: <variable_name> <data type>; Data Types NUMBER, VARCHAR2, DATE, etc. %TYPE: Takes the data type from the table. Syntax: <variable_name> <Table>.<Column>%TYPE; %ROWTYPE: Creates a record with fields for each column of the specified table. Syntax: <variable_name> <Table>%ROWTYPE;
VARIABLE DECLARATION Some rules: All variables have to be declared in the Declare Section. Each variable declaration is a separate statement. Variable Declaration Examples: count NUMBER := 5; fname VARCHAR2(15); fn Employee.fname%TYPE; emprec Employee%ROWTYPE;
PL/SQL - EXECUTABLE SECTION Some general rules: PL/SQL is case insensitive. Statements end with a semicolon. Put / after the code block for it to compiled/executed.
PL/SQL - EXECUTABLE SECTION Some Details: Assignment is := Example: val:=5; Comments: - Single line comment - Multi line comment /... / DDL statements (Create, Drop, Alter) are disallowed. Output on Screen SET SERVEROUTPUT ON; DBMS_OUTPUT.PUT(); DBMS_OUTPUT.PUT_LINE(); Example: DBMS_OUTPUT.PUT_LINE( Test Message );
PL/SQL - EXCEPTIONS An exception is a warning/error arising during execution. Types of exceptions: Internally-Defined Exceptions (Raised Automatically): SQLCODE Value Exception -1 DUP_VAL_ON_INDEX -1476 ZERO_DIVIDE -1422 TOO_MANY_ROWS TABLE: Some example internally-defined exceptions Example error messages you see: * Error: ORA-00001: unique constraint (...) violated * Error: ORA-01476: divisor is equal to zero User-Defined Exceptions (Raised Manually): You can define your own exceptions and how to handle them...
EXCEPTIONS Syntax: EXCEPTION WHEN exception1 THEN... [WHEN exception2 THEN...] [WHEN OTHERS THEN...] Note: If your block has an exception section then it cannot be empty. i.e. it must have at least one WHEN statement.
PL/SQL - USER-DEFINED EXCEPTIONS To define a new exception: 1 Declare it (i.e. give it a name) in the Declare Section. 2 Add a handler (the code that will be executed when the exception is raised) for it in the Exception Section. DECLARE insufficient_funds EXCEPTION; balance NUMBER(7,2):= 180; BEGIN IF balance < 250 THEN RAISE insufficient_funds; END IF; EXCEPTION WHEN insufficient_funds Then DBMS_OUTPUT.PUT_LINE( insufficient funds ); END; /
STATEMENTS IN PL/SQL Conditional Statements IF-THEN-ELSE, CASE Iterative Statements LOOP, FOR-LOOP, WHILE-LOOP Sequential Flow-of-Control Statements EXIT-WHEN
CONDITIONAL STATEMENT IF Statement Syntax: IF <condition 1> THEN <statements> ELSIF <condition 2> THEN <statements> ELSE <statements> END IF; Remarks: Equality operator is = Inequality operators are!=, <>, ˆ= or =
CONDITIONAL STATEMENT IF Statement Example: IF salary <= 1000 THEN DBMS_OUTPUT.PUT_LINE( Low Income ); ELSIF salary > 1000 and salary <= 3000 THEN DBMS_OUTPUT.PUT_LINE( Avg Income ); ELSIF salary > 3000 and salary <= 4000 THEN DBMS_OUTPUT.PUT_LINE( Moderate Income ); ELSE DBMS_OUTPUT.PUT_LINE( High Income ); END IF;
CONDITIONAL STATEMENT CASE Statement Syntax: CASE [expression] WHEN condition_1 THEN result_1... WHEN condition_n THEN result_n ELSE result END CASE;
CONDITIONAL STATEMENT CASE Statement Example 1: CASE gender WHEN M THEN DBMS_OUTPUT.PUT_LINE( Male ); WHEN F THEN DBMS_OUTPUT.PUT_LINE( Female ); ELSE DBMS_OUTPUT.PUT_LINE( Unknown ); END CASE; Example 2: CASE WHEN a < b THEN DBMS_OUTPUT.PUT_LINE( a < b ); WHEN d < e THEN DBMS_OUTPUT.PUT_LINE( d < e ); END CASE;
LOOPS OPEN LOOP Syntax: LOOP <statements> END LOOP; Statements must include Exit When <condition> or loop will continue forever. Example: num := 1; LOOP INSERT INTO Table1 VALUES (num); EXIT WHEN num = 15; num := num +1; END LOOP;
LOOPS FOR LOOP Syntax: FOR var IN [REVERSE] start..end LOOP <statements> END LOOP; Remarks: You cannot change the value of the index inside the body of the loop. You can only increment by 1. Example: FOR num IN 1..15 LOOP INSERT INTO Table1 VALUES (num); END LOOP;
LOOPS WHILE LOOP Syntax: Example: WHILE <condition> LOOP <statements> END LOOP; num := 1; WHILE num<=15 LOOP INSERT INTO Table1 VALUES (num); num := num + 1; END LOOP;
CURSORS Inside a PL/SQL program, the result of a SELECT must go somewhere: If SELECT returns EXACTLY 1 row, it can go INTO a variable: DECLARE bal Account.balance%TYPE; BEGIN SELECT balance into bal FROM Account where id =1000; END; Possible exceptions with SELECT INTO are TOO_MANY_ROWS NO_DATA_FOUND What if SELECT returns multiple/no rows?
CURSORS CURSOR: is a variable that runs through the result of a SELECT, row by row. Syntax: CURSOR How to use: <curname> IS <SELECT Query>; 1 Open the cursor before you iterate through it: OPEN curname; 2 Use inside a cursor loop: * Fetch one result row at a time: FETCH curname INTO var; * Stop when there are no more rows to return: EXIT WHEN curname%notfound; 3 CLOSE after use: CLOSE curname;
MORE ABOUT CURSORS Example Table: CREATE TABLE Employee( empno NUMBER, name VARCHAR2(30), salary NUMBER(9,2), constraint pk_emp primary key (empno) );
MORE ABOUT CURSORS Example: DECLARE thisemp Employee%ROWTYPE; CURSOR curemp IS SELECT * FROM Employee; BEGIN OPEN curemp; LOOP FETCH curemp INTO thisemp; EXIT WHEN (curemp%notfound); IF (thisemp.salary < 1500) THEN DBMS_OUTPUT.PUT_LINE( Name: thisemp.name); END IF; END LOOP; CLOSE curemp; END; /
STORED PROCEDURES Syntax: CREATE [OR REPLACE] PROCEDURE <procname>([arguments]) {AS IS} /* Declaration Section */ BEGIN /* Executable Section - Required */ END [<procname>]; Parameter Modes IN (default) Read-Only OUT Write-Only IN OUT Read & Write
STORED PROCEDURES Executing Procedures EXECUTE <procname>(<parameters>); Examples: EXECUTE insertemp(12, Adam Smith,3000); EXECUTE printtotal;
STORED PROCEDURES Example: CREATE OR REPLACE Procedure GetDate(name IN VARCHAR2) AS BEGIN DBMS_OUTPUT.PUT( Hi name); DBMS_OUTPUT.PUT_LINE(. Today is: SYSDATE); END GetDate; / To call the procedure: Begin GetDate( Chris ); End; /
STORED FUNCTIONS Syntax: CREATE [OR REPLACE] FUNCTION <funname>([arguments]) RETURN datatype {AS IS} /* Declaration Section */ BEGIN /* Executable Section - Required */ END [<funname>]; You need to call a Function from another Procedure or Function.
STORED FUNCTIONS Example: CREATE OR REPLACE FUNCTION getsal (ename VARCHAR2) RETURN NUMBER AS lsalary Employee.salary%TYPE; BEGIN SELECT salary INTO lsalary FROM Employee WHERE name = ename; RETURN lsalary; END getsal; Example of calling a Function: BEGIN DBMS_OUTPUT.PUT_LINE(getSal( Adam Smith )); END;
STORED PROCEDURES/FUNCTIONS Viewing Errors PL/SQL does not always tell you about compilation errors. If you don t see what is wrong immediately, try: SHOW ERRORS; SHOW ERRORS PROCEDURE <procname>; Alternatively, check the User_Errors table...
STORED PROCEDURES/FUNCTIONS Your Objects To find out what Procedures/Functions you have created, use the following SQL query: SELECT * FROM User_Objects WHERE object_type = PROCEDURE OR object_type = FUNCTION ; To delete a stored Procedure/Function: DROP PROCEDURE <procname>; DROP FUNCTION <funname>;
PRIVILEGES NEEDED To create a Procedure/Function you must have either of the privileges: CREATE PROCEDURE CREATE ANY PROCEDURE You can only call a Procedure/Function if you are the owner of the object or have EXECUTE privilege on the object: GRANT EXECUTE ON <procedure_name> TO <user_name>; EXECUTE ANY PROCEDURE