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;
/
© Copyright 2026 Paperzz