PL/SQL

DATABASE PROGRAMS
CS 260
Database Systems
Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
Introduction


A database program is used to automate data
processing
It is written using a procedural language extension
that is specific to the DBMS
 Oracle:
PL/SQL
 “Procedural
Language/Structured Query Language”
 MySQL:
MySQL
 Microsoft SQL Server: T-SQL
 “Transact-SQL”
 IBM
DB2: SQL PL
 DB2
also runs PL/SQL
Introduction

Why do we need database programs?

Addresses the limitations of SQL commands
SQL has no conditional statements or looping mechanisms
 Database programs are helpful for importing and exporting data
 You can only go so far with nested queries
 An SQL query returns a tabular result set, stored programs can
manipulate this format


Why not just put stored program logic in an application?
“Stored programs” are accessible to any application using the db
 Database programs interface directly with the database



More efficient in terms of both speed and lines of code
DBMS can manage security issues
Introduction

Why might we want to avoid database programs?
 They
increase the DBMS server’s load
 Writing the program logic in an external application
may allow for more flexibility
 Database programs may be more difficult to debug
Introduction

PL/SQL Example
 This
stored program identifies the number of days until
Christmas
CREATE OR REPLACE FUNCTION shopping_days_xmas(current_date IN
DATE)
RETURN NUMBER IS shopping_days NUMBER;
BEGIN
shopping_days :=
TO_DATE('25-DEC-2015', 'DD-MON-YYYY') - current_date;
RETURN shopping_days;
END;
Introduction

Types of PL/SQL programs

Anonymous blocks
Not persistent (not stored in the database)
 Cannot be called by other programs
 No parameters/arguments


Stored programs

Stored as database objects




Procedures
Functions
Packages
Triggers
Can be called by other programs
 Allow parameters/arguments

Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
PL/SQL Language Basics

Basic program structure
 Statements
may span multiple lines and end with a
semicolon
 Text is not case sensitive
 Basic anonymous block program syntax
/* block comment */
DECLARE
<variable declarations>;
BEGIN
<program statements>; --line comment
EXCEPTION
<error handling statements>;
END;
PL/SQL Language Basics

Variables
 Names
must follow the Oracle object naming standard
 Names should be descriptive
 Naming conventions
 Use
lowercase letters with words separated by underscores
 Example: current_student_id
PL/SQL Language Basics

PL/SQL is a strongly-typed language
 All
variables must be declared with a type prior to use
 Declaration syntax
<variable_name> <data_type>;
 Declaration
example
current_student_id NUMBER(6);
 Initialization
example
current_student_id NUMBER(6) := 1;
PL/SQL Language Basics

Common data types

SQL data types
VARCHAR2, CHAR
 NUMBER
 DATE


Non-SQL data types

Integers


Real numbers



BINARY_INTEGER, INTEGER, INT, SMALLINT, …
DEC, DECIMAL, DOUBLE, PRECISION, NUMBERIC, REAL, …
BOOLEAN
Composite data types

RECORD, TABLE, VARRAY
PL/SQL Language Basics

Reference data types
 %TYPE
 Assumes
the data type of a database field
 Variable declaration example
current_cust_name candy_customer.cust_name%TYPE;
 %ROWTYPE
 Creates
a RECORD data type that holds the data types
present in the returned SQL query


RECORDS are ordered collections of specific data types
%ROWTYPE creates a RECORD according to the types in a result
 Syntax
<variable_name> <cursor_name>%ROWTYPE;
PL/SQL Language Basics

Basic Operators
Exponentiation
**
Multiplication
*
Division
/
Addition/Subtraction
+/-
Assignment
:=
Comparison
=
Concatenation
||
PL/SQL Language Basics

Displaying PL/SQL output using Oracle SQL
Developer
 Enable
and/or increase memory buffer
SET SERVEROUTPUT ON SIZE 4000;
 Necessary
 Output
to see PL/SQL output on the console
data to the console
DBMS_OUTPUT.PUT_LINE(‘<output>’);
DBMS_OUTPUT.PUT_LINE(‘Output: ’ || <variable or function>);
PL/SQL Language Basics

Anonymous block example
 This
program prints the current date to the console in
the format “Today is <date>”
SET SERVEROUTPUT ON SIZE 4000;
DECLARE
todays_date DATE;
BEGIN
todays_date := SYSDATE;
DBMS_OUTPUT.PUT_LINE ('Today is ' || todays_date);
END;
PL/SQL Language Basics

Anonymous block example output
Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
Conditions and Loops

Conditional statements
 Syntax
IF <condition> THEN
<statements>;
ELSIF <condition> THEN
<statements>;
ELSE
<statements>;
END IF;
0
or more “ELSIF” statements
 Optional “ELSE” statement
Conditions and Loops

Conditional statement example

This program extends the functionality of the previous
program by also indicating whether Christmas is coming or
has passed
DECLARE
todays_date DATE;
BEGIN
todays_date := SYSDATE;
DBMS_OUTPUT.PUT_LINE ('Today is ' || todays_date);
IF todays_date > to_date('25-JUN', 'DD-MON') THEN
DBMS_OUTPUT.PUT_LINE ('Christmas is coming!');
ELSE
DBMS_OUTPUT.PUT_LINE ('Christmas has passed.');
END IF;
END;
Conditions and Loops

EXIT WHEN loop (equivalent to Java do-while loop)
 Syntax
 Example
LOOP
<statements>;
EXIT WHEN <condition>;
END LOOP;
DECLARE
i NUMBER;
BEGIN
i := 0;
LOOP
i := i+1;
DBMS_OUTPUT.PUT_LINE ('i is ' || i);
EXIT WHEN i = 10;
END LOOP;
END;
Conditions and Loops

WHILE loop (equivalent do Java while loop)
 Syntax
WHILE <condition>
LOOP
<statements>;
END LOOP;
 Example
DECLARE
i NUMBER;
BEGIN
i := 0;
WHILE i < 10
LOOP
i := i+1;
DBMS_OUTPUT.PUT_LINE ('i is ' || i);
END LOOP;
END;
Conditions and Loops

FOR loop (equivalent do Java for loop)
 Syntax
FOR <counter> IN <start_value> .. <end_value>
LOOP
<statements>;
END LOOP;
 Example
You cannot manually update the
BEGIN
for loop counter within the loop
FOR i IN 1 .. 10
LOOP
DBMS_OUTPUT.PUT_LINE ('i is ' || i);
END LOOP;
END;
Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
Cursors and SQL in PL/SQL

Using SQL within a PL/SQL Program
SQL Command Purpose
Category
Data Definition Change
Language (DDL) database
structure
Examples
CREATE,
ALTER,
GRANT,
REVOKE
Data
View or change SELECT,
Manipulation
data
INSERT,
Language (DML)
UPDATE,
DELETE
Transaction
Create logical COMMIT,
Control
transactions
ROLLBACK
Can be
used in
PL/SQL
No
Yes
Yes
Cursors and SQL in PL/SQL

Example looping program
--create table to store all dates in 2015
CREATE TABLE dates_2015 ( date_value DATE );
--program to insert dates
SQL can exist in the same script as PL/SQL
SET SERVEROUTPUT ON SIZE 4000;
DECLARE
first_date DATE := '01-JAN-2015';
counter INT := 0;
BEGIN
DML and Transaction control can exist within PL/SQL
WHILE counter < 365
LOOP
INSERT INTO dates_2015 VALUES (first_date + counter);
DBMS_OUTPUT.PUT_LINE(first_date + counter);
counter := counter + 1;
END LOOP;
COMMIT;
END;
Cursors and SQL in PL/SQL

Using SELECT commands in PL/SQL
 Create
a “cursor” to allow the PL/SQL program to
reference the retrieved values
 Cursor:
“CURrent Set Of Records”
 Pointer to a memory location on the database server
 Cursor
types
 Implicit
 Explicit
Cursors and SQL in PL/SQL

Implicit cursors
 Can
be used for SELECT queries that return one (and
only one) record
 The
 Can
query must return a record
be used to assign the column values returned by a
SELECT statement into one or more variables
 The variables need to be declared, but the cursor itself
does not
Cursors and SQL in PL/SQL

Implicit cursors
 Syntax
SELECT <field1>, <field2>, …
INTO <variable1>, <variable2>, …
FROM <table>
WHERE <search_condition_that_will_return_a_single_record>;
 Usage
 The
number of variables in the INTO clause must match the
number of fields in the SELECT clause
 The corresponding field/variable data types must be
compatible

%TYPE may be useful here
Cursors and SQL in PL/SQL

Implicit cursor example
 This
program places the cust_name and cust_addr of
the candy_customer with a cust_id = 1 into the
program’s curr_cust_name and curr_cust_add variables
DECLARE
curr_cust_name candy_customer.cust_name%TYPE;
curr_cust_add candy_customer.cust_addr%TYPE;
BEGIN
SELECT cust_name, cust_addr
INTO curr_cust_name, curr_cust_add
FROM candy_customer
WHERE cust_id = 1;
DBMS_OUTPUT.PUT_LINE(curr_cust_name);
DBMS_OUTPUT.PUT_LINE(curr_cust_add);
END;
Cursors and SQL in PL/SQL

Explicit cursors
 Can
be used for SELECT queries that return zero, one,
or multiple records
 Can be used to assign the column values returned by a
SELECT statement into one or more variables
 Both the variables and the cursor need to be declared
 Explicit cursors are processed sequentially using a loop
 The
loop typically iterates through each record in the result
set
 The cursor points to the current record
Cursors and SQL in PL/SQL

Using an explicit cursor
1.
2.
3.
4.
Declare the cursor in the DECLARE section
Open the cursor in the program
Fetch the cursor result into PL/SQL program variables
Close the cursor
Cursors and SQL in PL/SQL

Explicit cursor example
 This
program loops through all candy_customer cust_id
and cust_name values obtained using a cursor and
prints them to the console
DECLARE
CURSOR customer_cursor IS
SELECT cust_id, cust_name FROM candy_customer;
curr_id candy_customer.cust_id%TYPE;
curr_name candy_customer.cust_name%TYPE;
BEGIN
OPEN customer_cursor;
LOOP
FETCH customer_cursor INTO curr_id, curr_name;
EXIT WHEN customer_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(curr_id || ' ' || curr_name);
END LOOP;
CLOSE customer_cursor;
END;
Cursors and SQL in PL/SQL

Alternate version of explicit cursor example
 Uses
a single variable of %ROWTYPE data type
instead of separate variables for each field
DECLARE
CURSOR customer_cursor IS
SELECT cust_id, cust_name FROM candy_customer;
customer_row customer_cursor%ROWTYPE;
BEGIN
OPEN customer_cursor;
LOOP
FETCH customer_cursor INTO customer_row;
EXIT WHEN customer_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(customer_row.cust_id || ' ' ||
customer_row.cust_name);
END LOOP;
CLOSE customer_cursor;
END;
Cursors and SQL in PL/SQL

Processing an explicit cursor
 Using
a cursor FOR loop
 Special
syntax just for explicit cursors
 Automatically opens, processes, and closes the cursor
 Automatically terminates after all cursor records are
processed
 Allows for much less code
Cursors and SQL in PL/SQL

Previous example using a cursor FOR loop
DECLARE
CURSOR customer_cursor IS
SELECT cust_id, cust_name FROM candy_customer;
customer_row customer_cursor%ROWTYPE;
BEGIN
FOR customer_row IN customer_cursor
LOOP
--process each row
DBMS_OUTPUT.PUT_LINE(customer_row.cust_id || ' ' ||
customer_row.cust_name);
END LOOP;
END;
Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
Exception Handling

Exception handling
 An
exception may occur due to a runtime error or an
event that violates a business rule
 If the exception isn’t handled, the program will
terminate and a default error message will be
displayed
 If the exception is handled, the program can continue
executing and/or a custom error message can be
displayed
Exception Handling

Program flow with and without exception handling
without
Program Body
error
with
Program Body
error
Exception handlers
System displays
a default error message
and program terminates
System can display a
custom error message
Program optionally
executes
additional statements
Exception Handling

Exception types
 Predefined
(named)
 Most
common system errors have corresponding named
exceptions
 User-defined
 Handle
application specific errors (business rules)
 Undefined
 Used
(named)
(unnamed)
for less common system errors
 Built-in exception handler is associated with the ORA error
code number
Exception Handling

Syntax for handling predefined named exceptions
DECLARE
<statements>;
BEGIN
<statements>;
EXCEPTION
WHEN <exception_name> THEN
<statements>;
END;
Exception Handling

Common PL/SQL named exceptions
Exception Handling

Handling a predefined named exception example


This program retrieves and prints a cust_name to the console, but
inappropriately retrieves more than one record using an implicit
cursor
The “TOO_MANY_ROWS” named exception is handled
DECLARE
curr_cust_id candy_customer.cust_id%TYPE;
curr_cust_name candy_customer.cust_name%TYPE;
BEGIN
SELECT cust_name
INTO curr_cust_name
FROM candy_customer;
DBMS_OUTPUT.PUT_LINE(curr_cust_name);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Change your query so it'
|| ' retrieves only one record');
END;
Exception Handling

Syntax for creating, raising, and handling user-defined
exceptions
 Declare exception as a variable in the DECLARE section
 Raise the exception in the program (in the BEGIN
section) when appropriate using the RAISE command
DECLARE
<exception_name> EXCEPTION;
BEGIN
RAISE <exception_name>;
EXCEPTION
WHEN <exception_name> THEN
<statements>;
END;
Exception Handling

Creating, raising, and handling a user-defined
exception example
DECLARE
curr_purch_id candy_purchase.purch_id%TYPE := 1;
curr_purch_date candy_purchase.purch_date%TYPE;
new_delivery_date DATE := '05-SEP-07';
e_invalid_date EXCEPTION;
BEGIN
SELECT purch_date INTO curr_purch_date FROM candy_purchase
WHERE purch_id = curr_purch_id;
IF curr_purch_date <= new_delivery_date THEN
UPDATE candy_purchase SET delivery_date = new_delivery_date
WHERE purch_id = curr_purch_id;
ELSE
RAISE e_invalid_date;
END IF;
COMMIT;
EXCEPTION
WHEN e_invalid_date THEN
DBMS_OUTPUT.PUT_LINE('Delivery date cannot be before
purchase date, please change it');
END;
Exception Handling

Syntax for handling unnamed exceptions
Unnamed exceptions can be identified by their SQL codes
 Named exceptions must be handled first
 The SQLERRM function returns a message describing the error


Potentially useful when handling an unnamed exception
DECLARE
<statements>;
BEGIN
<statements>;
EXCEPTION
-- handle named exceptions first
WHEN OTHERS THEN
IF SQLCODE = <sqlcode> THEN
<statements>;
END;
Exception Handling

Handling an unnamed exception example
DECLARE
new_candy_product_id candy_product.prod_id%TYPE := 100;
BEGIN
--update an FK value using a non-existent value
UPDATE candy_purchase
SET prod_id = new_candy_product_id
WHERE purch_id = 1;
EXCEPTION
-- ...named exception handlers
WHEN OTHERS THEN
IF SQLCODE = -2291 THEN
DBMS_OUTPUT.PUT_LINE('Product ID ' ||
new_candy_product_id || ' does not exist.');
DBMS_OUTPUT.PUT_LINE('Message: ' || SQLERRM );
END IF;
END;
SQL code list: http://psoug.org/oraerror.htm
Exception Handling

Exception scope and propagation
 Exception
handlers only handle exceptions thrown in
their BEGIN block
 Nested blocks can be created so that outer block
execution isn’t impacted by inner block exceptions
 After
an exception is raised and handled, all uncommitted
transactions are rolled back
 Execution resumes in the outer block
Exception Handling

Nested block syntax
DECLARE
<outer block declarations>;
BEGIN
<outer block statements>;
DECLARE
<inner block declarations>;
BEGIN
<inner block statements>;
EXCEPTION
<inner block exception handlers>;
END;
<more outer block statements>;
EXCEPTION
<outer block exception handlers>;
END;
Exception Handling


Suppose the cust_type of “W” was assumed to be
removed and updated for all customers in our
candy database
Write an anonymous block that does the following:
 Print
the name and cust_type of each customer
 If the cust_type is anything other than ‘P’ or ‘R’, raise a
custom “invalid_cust_type” exception
 If this exception is raised, the program should print the
name and invalid cust_type and continue processing
Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
Stored PL/SQL Programs



Can be executed by other programs and users
Can accept input parameters
They’re database objects
Permissions must be granted as needed
 Names must be unique in their schemas
 Follow object naming standards and conventions



Stored in a compiled form
Types of stored PL/SQL programs
Procedures
 Functions
 Packages
 Triggers

Stored PL/SQL Programs

Parameter modes

IN
Default parameter mode (used if no mode is specified)
 Used to pass values into the program
 Similar to Java’s pass-by-value argument passing scheme


OUT

Used to pass values out of the program


Acts like an uninitialized variable


Useful for procedures as they cannot “return” values
It should be assigned a value
IN OUT
Used to both pass values into and out of the program
 Similar to C++’s pass-by-reference argument passing scheme

Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
Stored Procedures

Stored procedures allow parameters, can call other
programs, but cannot return a value
 Syntax
Header
Body
CREATE OR REPLACE PROCEDURE <procedure_name>
(<param1> <mode> <datatype>,
<param2> <mode> <datatype>, …)
IS
“AS” can be used in place of “IS”
<variable declarations>;
BEGIN
<program statements>;
EXCEPTION
<exception handlers>;
END;
/
Stored Procedures

Stored procedure example
CREATE OR REPLACE PROCEDURE update_delivery_date
(curr_purch_id IN candy_purchase.purch_id%TYPE,
new_delivery_date IN DATE)
IS
-- local variable
curr_purch_date candy_purchase.purch_date%TYPE;
BEGIN
-- implicit cursor (only one row returned)
SELECT purch_date INTO curr_purch_date FROM candy_purchase
WHERE purch_id = curr_purch_id;
IF curr_purch_date <= new_delivery_date THEN
UPDATE candy_purchase SET delivery_date = new_delivery_date
WHERE purch_id = curr_purch_id;
DBMS_OUTPUT.PUT_LINE('Delivery date updated');
END IF;
COMMIT;
END;
/
Stored Procedures

Calling a stored procedure
 Stored
procedures can be called from an SQL script or
a PL/SQL program
 SQL script syntax
EXECUTE <procedure_name>(<comma separated list of arguments);
 Example
EXECUTE update_delivery_date (1, SYSDATE);
 PL/SQL
example (anonymous block)
BEGIN
update_delivery_date (1, SYSDATE);
END;
Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
Stored Functions

Stored functions are similar to stored procedures,
but they return a single value
 Syntax
Header
Body
CREATE OR REPLACE FUNCTION <function_name>
(<param1> <mode> <datatype>,
<param2> <mode> <datatype>, …)
RETURN <datatype>
IS
“AS” can be used in place of “IS”
<variable declarations>;
BEGIN
<program statements>;
RETURN <value>;
EXCEPTION
<exception handlers>;
RETURN <value>;
Exception handlers should return a value
END;
/
Stored Functions

Stored function example
CREATE OR REPLACE FUNCTION calc_diff
(date1 IN DATE, date2 IN DATE)
RETURN NUMBER
IS
days_passed NUMBER;
BEGIN
days_passed := date1 - date2;
RETURN days_passed;
END;
/
 Example
call from an SQL script
SET SERVEROUTPUT ON SIZE 4000;
EXEC DBMS_OUTPUT.PUT_LINE(calc_diff('25-DEC-2014', SYSDATE));
Stored Functions

Calling a stored function
 Stored
functions can also be called from within an SQL
statement or a PL/SQL program
 Syntax
 Can
be called anywhere a value of the return type is
allowed
 Examples
SELECT purch_id, calc_diff(delivery_date, purch_date)
FROM candy_purchase;
SELECT purch_id
FROM candy_purchase
WHERE calc_diff(delivery_date, purch_date) > 0;
Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
Packages


A package is an object that groups related PL/SQL
objects, such as variables, cursors, procedures, and
functions
It consists of a specification and a body

Specification


Body


Declares a public interface
Contains a private implementation
Clients can reference and call objects declared in the
specification, but not those declared in the body

Similar to header and source files in C++
Packages

Benefits of packages
 Encapsulation
of related objects
 Information hiding
 Clients
cannot see the implementation details in the body
 If a procedure is declared in the body (and not the
specification), it can be called only from within the package
body
 Better
performance
 Package

specifications and bodies are compiled separately
If changes to the body are needed, only the package body
needs to be recompiled instead of all clients that call objects in
the package body
Packages

Package specification syntax
CREATE OR REPLACE PACKAGE <package_name>
IS
--public variables and cursors
<variable_name> <datatype>;
CURSOR <cursor_name> IS
<SQL_statement>;
…
--procedures & functions
PROCEDURE <procedure_name> (<parameter_list>);
FUNCTION <function_name> (<parameter_list>) RETURN <data type>;
…
END;
/
Packages

Package specification example
CREATE OR REPLACE PACKAGE purchase_package IS
--public variable declarations
max_pounds NUMBER := 100;
curr_purch_id candy_purchase.purch_id%TYPE;
--procedure declarations
PROCEDURE update_pounds (new_pounds IN NUMBER);
PROCEDURE update_delivery_date (new_delivery_date IN DATE);
END;
/

The public variables “max_pounds” and “curr_purch_id” can
be used within the “update_pounds” and
“update_delivery_date” implementations

They can also be used anywhere access to the package is allowed
Packages

Example package body
Procedure 1
Procedure 2
CREATE OR REPLACE PACKAGE BODY purchase_package IS
PROCEDURE update_delivery_date (new_delivery_date DATE)
IS
curr_purch_date candy_purchase.purch_date%TYPE;
BEGIN
SELECT purch_date INTO curr_purch_date FROM candy_purchase
WHERE purch_id = curr_purch_id;
IF curr_purch_date <= new_delivery_date THEN
UPDATE candy_purchase SET delivery_date = new_delivery_date
WHERE purch_id = curr_purch_id;
END IF;
COMMIT;
END;
PROCEDURE update_pounds (new_pounds NUMBER)
IS
BEGIN
IF new_pounds <= max_pounds THEN
UPDATE candy_purchase SET pounds = new_pounds
WHERE purch_id = curr_purch_id;
END IF;
COMMIT;
END;
END;
/
Packages

When referencing or calling an object in a
package, it is prefaced with its package name
 Syntax
<package_name>.<reference/call>;
 Example
(called from an SQL script)
EXECUTE purchase_package.curr_purch_id := 1;
EXECUTE purchase_package.update_pounds(3.7);
 The
EXECUTE command isn’t used when referencing or
calling package objects from within a PL/SQL block
 For example, dbms_output.put_line(‘…’); is an example of
calling a procedure inside the dbms_output package
Packages

When creating a package body, use the SHOW
ERRORS command to print errors to the console
<package body>
/
SHOW ERRORS;

Oracle built-in packages
 Provide
support for basic database functionality
 Owned by the SYS database schema
 Visible using the “Connections” pane in Oracle SQL
Developer
 Expand
your schema > Other Users > SYS > Packages
Overview


Introduction
Anonymous blocks
 Oracle’s
PL/SQL language basics
 Conditions and loops
 Cursors and SQL commands in PL/SQL
 Exception handling

Stored programs
 Procedures
 Functions
 Packages
 Triggers
Triggers


Database triggers are programs that are attached
to specific database tables
They may be executed in response to the following
table operations:
 INSERT
 UPDATE
 DELETE
Triggers

Why are triggers useful?
 Force
related operations to always happen
 Update
a “quantity on hand” field whenever an item is sold
 Update a “current enrollment total” field whenever a student
enrolls in a course section
 Create
an audit trail
 Record
the username and IP address of every user who
changes a table

For example, record who changed a student grade, when they
changed it, what they changed it from, and what they changed it
to
Triggers

When defining a trigger, the following must be
specified:
 Operation
 INSERT,
that causes the trigger to fire
UPDATE, or DELETE
 Timing
 BEFORE
or AFTER the operation occurs
 Level
 STATEMENT
or ROW
Triggers

Trigger timing
 BEFORE
 The
trigger fires before the statement executes
 For example, for an audit trail, record the old grade value
before it is updated

Though it’s still possible to accomplish this using AFTER
 AFTER
 The
trigger fires after the statement executes
 For example, update the “quantity on hand” after an item is
sold
Triggers

Trigger levels
 ROW
 The
trigger fires once for each row that is affected
 For example, update a corresponding “quantity on hand”
value for each item that was sold
 STATEMENT
 The
trigger fires once regardless of how many rows are
updated
 For example, for an audit trail, you just want to record that
someone updated a table, but you don’t care how many
rows were updated
Triggers

Restrictions
 Triggers
cannot have any parameters
 Triggers can only be created on tables that you own
 Triggers cannot execute a COMMIT command
 This

is handled by the transaction firing the trigger
Triggers can be enabled or disabled
ALTER TRIGGER <trigger_name> <ENABLE or DISABLE>;
Triggers

Creation syntax
CREATE OR REPLACE TRIGGER <trigger_name>
<BEFORE or AFTER> <INSERT or UPDATE or DELETE>
ON <table_name>
[FOR EACH ROW] [WHEN (<condition>)]
BEGIN
<trigger_body>;
END;
/



Choose one of “BEFORE” or “AFTER”
Choose one or more of “INSERT”, “UPDATE”, and “DELETE”,
separated by “OR”
“FOR EACH ROW” is optional


The trigger has statement level if omitted
“WHEN (<condition>)” is optionally used only at the ROW level

Causes trigger to fire only when the row satisfied the condition
Triggers

Statement level example
CREATE TABLE purchase_audit(
date_changed DATE,
user_changing VARCHAR2(30)
);
CREATE OR REPLACE TRIGGER purchase_audit
AFTER INSERT OR UPDATE OR DELETE ON candy_purchase
BEGIN
INSERT INTO purchase_audit VALUES (SYSDATE, USER);
END;
/
USER returns the database user executing the statement
SHOW ERRORS;
UPDATE candy_purchase SET pounds = 4.5
WHERE purch_id = 1 AND prod_id = 1;
SELECT * FROM purchase_audit;
Triggers

Row level example
CREATE TABLE purchase_audit_row
(purch_id NUMBER(9),
old_pounds NUMBER,
new_pounds NUMBER,
change_date DATE,
change_user VARCHAR2(30));
CREATE OR REPLACE TRIGGER purchase_audit_row
BEFORE UPDATE ON candy_purchase
FOR EACH ROW
BEGIN
INSERT INTO purchase_audit_row VALUES(
:OLD.purch_id, :OLD.pounds, :NEW.pounds, SYSDATE, USER);
END;
/
:OLD.<field_name> references a field’s old
SHOW ERRORS;
value
:NEW.<field_name> references a field’s new value
SELECT * FROM purchase_audit_row;
UPDATE candy_purchase SET pounds = 15 WHERE purch_id = 5;
SELECT * FROM purchase_audit_row;
Triggers

Trigger design (from Oracle)
 Triggers
should not duplicate features already built into
the database
 E.g.
Checking constraints
 If
size is much more than 60 lines, place logic in a
stored procedure and call from the trigger
 Triggers should not be recursive
 For
example, a trigger should not update a table if it’s been
designed to fire after updates are made to that table
 Causes out of memory errors
 Because
of their potentially frequent use, they should
be designed and implemented carefully
PL/SQL Programs in Scripts

Using PL/SQL programs in scripts
 PL/SQL
programs in a script must be followed by a
single forward slash
CREATE OR REPLACE PACKAGE show_message IS
PROCEDURE hello_world;
END;
/
CREATE OR REPLACE PACKAGE BODY show_message IS
PROCEDURE hello_world IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello World');
END;
END;
/
SET SERVEROUTPUT ON SIZE 4000;
BEGIN
show_message.hello_world();
END;
/