2. Overview
• Fundamentals of PL/SQL
– Control Structures and other PL/SQL language elements
• Oracle Types and Collections
• PL/SQL and Oracle Interaction
• Subprograms and Packages
• Error Handling
3. Fundamentals
• Building blocks of PL/SQL Code:
– Identifiers
– Reserved Words
– Literals
– Comments
– Data types
– Operators
6. Fundamentals
• Implicit Conversion
– Example - From CHAR to NUMBER
DECLARE
initial_time CHAR(5)
final_time CHAR(5)
Time_Diff NUMBER(5)
BEGIN
initial_time := to_char(sysdate, ‘SSSSS’);
…
final_time := to_char(sysdate, ‘SSSSS’);
Time_diff := initial_time – final_time;
END
7. Fundamentals
• Declarations
seconds_per_minute NUMBER := 60;
elapsed_minutes NUMBER := 20;
elapsed_seconds NUMBER :=
elapsed_minutes * seconds_per_minute ;
minutes_per_hour number DEFAULT 60;
user_name NOT NULL VARCHAR2(30) := ‘Infosys’;
order_number order.order_number %TYPE;
order order%ROWTYPE;
8. Fundamentals
• Case sensitivity
• Name resolution
• Scope and Visibility
DECLARE
x INTEGER;
BEGIN
DECLARE
y INTEGER;
BEGIN
…
END;
…
END;
9. Fundamentals
• LIKE operator
ename LIKE ‘J%SON’
• IS NULL operator
• BETWEEN operator
– A BETWEEN 1 AND 10
• IN operator
– ename in (NULL, ‘KING’, FORD’)
• Concatenation operator
– ‘Suit’ || ‘case’
10. Fundamentals
• Cursors
– Work areas
– Explicit cursors
• “Points to” the current row of the Result Set
• Similar to File processing
DECLARE CURSOR c1 IS SELECT empno, ename, job FROM emp WHERE
deptno = 20;
• OPEN, FETCH and CLOSE
11. Fundamentals
• CURSOR FOR loop
– Implicitly declares its loop index as a record that
represents a row fetched from the database
– Closes cursor at the end of the loop
DECLARE CURSOR c1 IS SELECT ename, sal, hiredate, deptno FROM emp; ...
BEGIN FOR emp_rec IN c1
LOOP
...
salary_total := salary_total + emp_rec.sal;
END LOOP;
END;
12. Fundamentals
• Cursor Variables
– unlike a cursor, a cursor variable can be opened for any
type-compatible query
PROCEDURE open_cv (generic_cv IN OUT GenericCurTyp,
choice NUMBER) IS
BEGIN
IF choice = 1 THEN
OPEN generic_cv FOR
SELECT * FROM emp;
ELSIF choice = 2 THEN
OPEN generic_cv FOR
SELECT * FROM dept;
END IF;
...
END;
13. Fundamentals
• Ref Cursor
– A cursor type where you can skip specifying
Structure, and thus can use the same cursor for
various structures.
TYPE my_ref_cur_type IS REF CURSOR;
my_ref_cursor my_ref_cur_type;
14. Fundamentals
• Attributes
– %TYPE
my_title books.title%TYPE;
– %ROWTYPE
DECLARE dept_rec dept%ROWTYPE; -- declare record variable
my_deptno := dept_rec.deptno;
DECLARE
CURSOR c1 IS
SELECT ename, sal, hiredate, job FROM emp;
emp_rec c1%ROWTYPE;
-- declare record variable that represents
-- a row fetched from the emp table
FETCH c1 INTO emp_rec;
15. Fundamentals
• Conditional Control – IF statement
– If-Then
– If-Then-Else
– If-Then-ElsIf
• Iterative Control
– Loop
– While-Loop
– For-Loop
– EXIT
– EXIT-WHEN
16. Fundamentals
• LOOP
LOOP
…
END LOOP;
• WHILE-LOOP
WHILE a < 10 LOOP
…
END LOOP
• FOR-LOOP
FOR i IN 1..3 [REVERSE] LOOP
…
END LOOP;
17. Fundamentals
DECLARE
acct_balance NUMBER(11,2);
acct CONSTANT NUMBER(4) := 3;
debit_amt CONSTANT NUMBER(5,2) := 500.00;
BEGIN
SELECT bal INTO acct_balance
FROM accounts WHERE account_id = acct
FOR UPDATE OF bal;
IF acct_balance >= debit_amt THEN
UPDATE accounts SET bal = bal - debit_amt
WHERE account_id = acct;
ELSE
INSERT INTO temp VALUES (acct, acct_balance,
'Insufficient funds');
-- insert account, current balance, and message
END IF;
END;
18. Fundamentals
• LOOP
LOOP
...
total := total + salary;
EXIT WHEN total > 25000; -- exit loop if condition is true
END LOOP;
• FOR LOOP
FOR i IN 1..order_qty
LOOP
UPDATE sales SET custno = customer_id
WHERE serial_num = serial_num_seq.NEXTVAL;
END LOOP;
19. Fundamentals
DECLARE
salary emp.sal%TYPE := 0;
mgr_num emp.mgr%TYPE;
last_name emp.ename%TYPE;
starting_empno emp.empno%TYPE := 7499;
BEGIN
SELECT mgr INTO mgr_num
FROM emp WHERE empno = starting_empno;
WHILE salary <= 2500 LOOP
SELECT sal, mgr, ename INTO salary, mgr_num,
last_name FROM emp WHERE
empno = mgr_num;
END LOOP;
END
20. Fundamentals
• Sequential Control
– GOTO statement lets you branch to a label unconditionally
IF rating > 90 THEN
GOTO calc_raise; -- branch to label
END IF;
...
<<calc_raise>>
IF job_title = 'SALESMAN' THEN -- control resumes here
amount := commission * 0.25;
ELSE
amount := salary * 0.10;
END IF;
22. Fundamentals
PROCEDURE award_bonus (emp_id NUMBER)
IS
bonus REAL;
comm_missing EXCEPTION;
BEGIN
SELECT comm * 0.15 INTO bonus
FROM emp WHERE empno = emp_id;
IF bonus IS NULL THEN
RAISE comm_missing;
ELSE
UPDATE payroll SET pay = pay + bonus WHERE
empno = emp_id;
END IF;
EXCEPTION WHEN comm_missing
THEN
...
END award_bonus;
23. Fundamentals
CREATE PACKAGE emp_actions AS
-- package specification
PROCEDURE hire_employee (empno NUMBER,
ename CHAR, ...);
PROCEDURE fire_employee (emp_id NUMBER);
END emp_actions;
CREATE PACKAGE BODY emp_actions AS -- package body
PROCEDURE hire_employee (empno NUMBER, ename CHAR, ...) IS
BEGIN
INSERT INTO emp VALUES (empno, ename, ...);
END hire_employee;
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM emp WHERE empno = emp_id;
END fire_employee;
END emp_actions;
24. Fundamentals
• RECORD
– %ROWTYPE attribute is used to declare a record that
represents a row in a table or a row fetched from a
cursor.
– You can create your own customized record types too.
25. Fundamentals
Some Oracle Concepts
• TRIGGERS
– 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.
– One of the many uses for database triggers is to audit data
modifications.
CREATE TRIGGER audit_sal AFTER UPDATE OF sal ON emp
FOR EACH ROW
BEGIN
INSERT INTO emp_audit VALUES ...
END;
26. Fundamentals
• Constraints
• Indexes
– indexes are useful because they sort the table on the indexed columns and
hence make the search faster
• Views
– Views in Oracle are windows to limited data
• Decode
SELECT DECODE (A, B, C, D).. means if A = B then C else D
SELECT DECODE (A, B, C, D, E, F).. means if A = B then C else if A
= D then E else F
CREATE OR REPLACE VIEW <viewname> AS
(SELECT DECODE(Total, 0, '', Total) Total FROM <tablename>);
27. Fundamentals
• GOTO usage
– The control cannot branch off into a IF statement,
LOOP statement or a sub-block
– You cannot pass control from IF into ELSE
• NULL statement
– The NULL statement explicitly specifies inaction
IF rating > 90 THEN
compute_bonus(emp_id);
ELSE
NULL;
END IF;
28. Collections
• - A collection is an ordered group of elements, all of the same
type.
– Each element has a unique subscript that determines its
position in the collection.
– Collections work like the arrays found in most third-
generation programming languages. Also, collections can be
passed as parameters.
– You can define collection types in a package, then use them
programmatically in your applications.
– Single dimensional only
29. Collections
– Also, you can pass collections as parameters. So, you
can use them to move columns of data into and out of
database tables or between client-side applications and
stored subprograms. In addition, collections can store
instances of an object type and can be attributes of an
object type.
• Two types of collections
– Items of type TABLE are nested tables
– Items of type VARRAY are varrays (short for variable-
size arrays)
31. Collections
• Array Vs Nested Table
• Varrays have a maximum size, but nested tables do not.
• Varrays are always dense, but nested tables can be sparse.
• Oracle stores varray data in-line (in the same table) unless it exceeds 4K, in which
case the data is stored out-of-line. But, Oracle stores nested table data out-of-line in
a store table, which is a system-generated database table associated with the nested
table.
• When stored in the database, varrays retain their ordering and subscripts, but nested
tables do not.
32. Collections
• When to use what?
– A varray is stored as an object, whereas a nested table
is stored in a storage table with every element mapped
to a row in the table. So, if you want efficient queries,
use nested tables.
– If you want to retrieve entire collection as a whole, use
varrays. However, when collections get very large, it
becomes impractical. So, varrays are better suited for
small collections.
33. Collections
Creating Arrays and Nested tables
CREATE TYPE address_type AS OBJECT
(house_number NUMBER,
city VARCHAR2(10),
phone_number NUMBER);
CREATE TYPE address_list_array AS VARRAY(4) OF address_type;
CREATE TYPE address_list_ntable AS TABLE OF address_type;
(An object table is a special kind of table in which each row represents an object)
CREATE TABLE customer (customer_number NUMBER,
date_of_joining DATE,
address_list address_list_ntable)
NESTED TABLE address_list STORE AS address_list_ntable_values;
34. Collections
Accessing Contents of Varrays
EXISTS
IF courses.EXISTS(i) THEN courses(i) := new_course; END IF;
COUNT
LIMIT
FIRST and LAST
PRIOR and NEXT
EXTEND
TRIM
DELETE
35. Collections
Accessing Nested Table contents
SELECT * FROM EMPLOYEES;
NAME
--------------------
ADDR(HOUSE, STREET, STATE)
---------------------------------------------------------------------
HOWARD ROGERS
ADDR_TABLE(ADDRESS('16 BRADEY AVENUE', 'HAMMONDVILLE', 'NSW'),
ADDRESS('4 JULIUS AVENUE',
'CHATSWOOD', 'NSW'))
SELECT E.NAME,A.HOUSE,A.STREET,A.STATE
2 FROM EMPLOYEES E, TABLE(E.ADDR)(+) A;
NAME HOUSE STREET STATE
--------------- ------------------------- -------------------- -----
HOWARD ROGERS 16 BRADEY AVENUE HAMMONDVILLE NSW
HOWARD ROGERS 4 JULIUS AVENUE CHATSWOOD NSW
36. Collections
Manipulating Varray elements
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
TYPE table_type IS VARRAY(5) OF NUMBER(10);
v_tab table_type;
v_idx NUMBER;
BEGIN
-- Initialise the collection with two values.
v_tab := table_type(1, 2);
-- Extend the collection with extra values.
<< load_loop >>
FOR i IN 3 .. 5
LOOP
v_tab.extend;
v_tab(v_tab.last) := i;
END LOOP load_loop;
-- Can't delete from a VARRAY.
-- v_tab.DELETE(3);
-- Traverse collection
v_idx := v_tab.FIRST;
<< display_loop >>
WHILE v_idx IS NOT NULL
LOOP
DBMS_OUTPUT.PUT_LINE('The number ' || v_tab(v_idx));
v_idx := v_tab.NEXT(v_idx);
END LOOP display_loop;
END;
37. Collections
• Manipulating Nested Table data
INSERT INTO EMPLOYEES VALUES (
'HOWARD ROGERS',
ADDR_TABLE(
ADDRESS ('16 BRADEY AVENUE','HAMMONDVILLE','NSW'),
ADDRESS ('4 JULIUS AVENUE','CHATSWOOD','NSW'))
);
UPDATE TABLE(SELECT ADDR FROM EMPLOYEES WHERE NAME='HOWARD ROGERS')
SET HOUSE = '15 BRADEY AVENUE'
WHERE HOUSE = '16 BRADEY AVENUE';
DELETE FROM
TABLE(SELECT ADDR FROM EMPLOYEES WHERE NAME='HOWARD ROGERS')
WHERE STREET = 'CHATSWOOD';
38. Collections
• Records
– A record is a group of related data items stored
in fields, each with its own name and datatype
DECLARE
TYPE StockItem IS RECORD ( item_no INTEGER(3) NOT NULL :=
999, description VARCHAR2(50), quantity INTEGER, price
REAL(7,2)); ...
BEGIN
...
END;
40. Oracle – PL/SQL
• A transaction is a series of SQL data manipulation
statements that does a logical unit of work. For example,
two UPDATE statements might credit one bank account
and debit another
• aggregate functions: AVG, COUNT, GROUPING, MAX,
MIN, STDDEV, SUM, and VARIANCE. Except for
COUNT(*), all aggregate functions ignore nulls
• SQL pseudocolumns: CURRVAL, NEXTVAL, ROWID,
and ROWNUM
• A sequence is a schema object that generates sequential
numbers
41. Oracle – PL/SQL
• Cursor Example
DECLARE
my_sal emp.sal%TYPE;
my_job emp.job%TYPE;
factor INTEGER := 2;
CURSOR c1 IS SELECT factor*sal FROM emp WHERE job = my_job;
BEGIN
...
OPEN c1; -- here factor equals 2
LOOP
FETCH c1 INTO my_sal;
EXIT WHEN c1%NOTFOUND;
factor := factor + 1; -- does not affect FETCH
END LOOP;
END;
42. Subprograms and Packages
• Packages
– The specification is the interface to your
applications; it declares the types, constants,
variables, exceptions, cursors, and subprograms
available for use.
– The body defines cursors and subprograms and
so implements the specification.
43. Subprograms and Packages
• Packages
– Only the declarations in the package specification are visible and
accessible to applications
– Implementation details in the package body are hidden and
inaccessible.
– Packages can be compiled and stored in an Oracle database, where
their contents can be shared by many applications. When you call
a packaged subprogram for the first time, the whole package is
loaded into memory. So, subsequent calls to related subprograms
in the package require no disk I/O. Thus, packages can enhance
productivity and improve performance
44. Subprograms and Packages
• Subprograms are named PL/SQL blocks that
can take parameters and be invoked. PL/SQL
has two types of subprograms called
procedures and functions
• extensibility
• modularity
• reusability
• maintainability
• abstraction
45. Subprograms and Packages
PROCEDURE raise_salary
(emp_id INTEGER, amount REAL)
IS
current_salary REAL;
salary_missing EXCEPTION;
BEGIN
SELECT sal INTO current_salary FROM emp WHERE
empno = emp_id;
IF current_salary IS NULL THEN
RAISE salary_missing;
ELSE UPDATE emp SET sal = sal + amount WHERE
empno = emp_id;
END IF;
EXCEPTION WHEN NO_DATA_FOUND THEN
INSERT INTO emp_audit VALUES (emp_id, 'No such number');
WHEN salary_missing
THEN INSERT INTO emp_audit VALUES (emp_id, 'Salary is
null');
END raise_salary;
46. Subprograms and Packages
• FUNCTION sal_ok (salary REAL,
title VARCHAR2)
RETURN BOOLEAN
IS
min_sal REAL;
max_sal REAL;
BEGIN
SELECT losal, hisal INTO min_sal, max_sal
FROM sals WHERE job = title;
RETURN (salary >= min_sal) AND (salary <= max_sal);
END sal_ok;
47. Subprograms and Packages
CREATE PACKAGE emp_actions
AS -- package spec
PROCEDURE hire_employee (emp_id INTEGER, name VARCHAR2, ...);
PROCEDURE fire_employee (emp_id INTEGER);
PROCEDURE raise_salary (emp_id INTEGER, amount REAL);
...
END emp_actions;
CREATE PACKAGE BODY emp_actions AS -- package body
PROCEDURE hire_employee (emp_id INTEGER, name VARCHAR2, ...) IS
BEGIN ...
INSERT INTO emp VALUES (emp_id, name, ...);
END hire_employee;
PROCEDURE fire_employee (emp_id INTEGER) IS
BEGIN
DELETE FROM emp WHERE empno = emp_id;
END fire_employee;
PROCEDURE raise_salary (emp_id INTEGER, amount REAL) IS
BEGIN
UPDATE emp SET sal = sal + amount WHERE empno = emp_id;
END raise_salary;
...
END emp_actions;
48. Error Handling
• When an error occurs, an exception is raised
• raise_application_error(error_number, message);
DECLARE
out_of_stock EXCEPTION;
number_on_hand NUMBER(4);
BEGIN
...
IF number_on_hand < 1 THEN RAISE
out_of_stock;
END IF;
EXCEPTION WHEN out_of_stock THEN
-- handle the error
END;