Course: MSc DS
SQL Programming
Module: 5
Learning Objectives:
1. Differentiate between predefined and user-defined
exceptions in PL/SQL.
2. Implement BEGIN... EXCEPTION... END blocks for error-
resistant code.
3. Identify the role and significance of database triggers.
4. Apply best practices in creating, managing, and optimising
triggers.
5. Classify and utilise row-level, statement-level, and
BEFORE, AFTER, and INSTEAD OF triggers.
6. Design PL/SQL solutions using exceptions and triggers for
real-world use cases.
Structure:
5.1 Understanding Exceptions
5.2 Predefined and User-Defined Exceptions
5.3 Exception Handling
5.4 Introduction to Triggers
5.5 Creating and Managing Triggers
5.6 Trigger Types: Row, Statement, Before, After, Instead Of
5.7 Summary
5.8 Keywords
5.9 Self-Assessment Questions
5.10 Case Study
5.11 Reference
5.1 Understanding Exceptions
Exceptions in PL/SQL are run-time errors and abnormal
conditions that can disrupt the normal flow of a PL/SQL
program. They can arise due to reasons such as invalid data,
resource unavailability, or unexpected scenarios not
anticipated in the regular programming flow.
Importance of Exceptions in PL/SQL:
● Predictable Program Behaviour: By handling exceptions,
a PL/SQL program can ensure that it behaves predictably
under unexpected scenarios, rather than crashing or
producing unreliable results.
● Enhanced User Experience: Exception handling allows for
the graceful handling of errors, providing meaningful
messages to the user rather than abrupt failures.
● Resource Management: Proper exception handling can
ensure that resources like database connections, files, or
memory are appropriately released or managed, even
when an error occurs.
● Maintaining Data Integrity: Exception handling can
prevent a program from proceeding with operations that
could result in corrupt or inconsistent data in the
database.
Role of Exceptions in Robust Database Programming:
Robust database programming seeks to produce programs that
are resilient, reliable, and resistant to failures, ensuring data
integrity and consistency. Here’s how exceptions play a pivotal
role in achieving this:
1. Error Detection:
● Exceptions enable the identification of errors and
unexpected conditions during runtime, which would
otherwise be hard to detect during compile-time or
testing phases.
2. Segmentation of Logic:
● By separating error handling logic from the main
business logic, the code becomes more readable,
maintainable, and modular. This isolation aids in
easy identification and modification of error-
handling routines without affecting the core logic.
3. Recovery Mechanisms:
● Exceptions provide the programmer with an
opportunity to implement recovery actions, like
retrying a failed operation, logging the error for
analysis, or redirecting to an alternate flow.
4. Consistent Response to Errors:
● By centralising the error-handling routines, a
consistent response or message can be presented to
end-users or calling systems. This uniformity can
improve the predictability of the system for both
users and developers.
5. Guarding Data Transactions:
● Exceptions are especially crucial when handling
transactions in a database environment. They can
ensure that transactions are either completely
successful or rolled back in case of errors, preserving
the atomicity and consistency of data operations.
5.2 Predefined and User-Defined Exceptions
PL/SQL inherently provides a plethora of predefined exceptions,
which are readily available for developers to utilise in
recognizing and handling common database-related errors.
● Standard Exceptions: These exceptions are automatically
raised by the Oracle Database whenever a related
database error occurs. For instance, when trying to insert
a null value into a non-null column, Oracle will
automatically raise the VALUE_ERROR exception.
● Named System Exceptions: These are exceptions that
have been given explicit names by Oracle. Examples
include NO_DATA_FOUND (raised when a SELECT INTO
statement returns no data) and TOO_MANY_ROWS
(raised when a SELECT INTO statement returns more than
one row).
Examples of Common Predefined Exceptions
Some common predefined exceptions PL/SQL developers often
encounter include:
● NO_DATA_FOUND: Raised when a SELECT INTO
statement retrieves no rows.
● TOO_MANY_ROWS: Elicited when a SELECT INTO
retrieves more than one row.
● VALUE_ERROR: Emerges when there's an arithmetic,
conversion, truncation, or size-constraint error.
● ZERO_DIVIDE: Triggered when an attempt to divide a
number by zero occurs.
Crafting Custom Exceptions for Specific Use Cases
There may arise scenarios where the built-in exceptions are not
sufficient to address specific error conditions pertinent to the
business logic. In these circumstances, PL/SQL permits
developers to craft their own user-defined exceptions.
● Advantages: User-defined exceptions offer granular
control, allowing developers to signal very specific error
conditions tailored to the business application's
requirements. By doing so, they can capture and handle
exceptions more efficiently, ensuring smoother end-user
experiences.
Implementing User-Defined Exceptions: A Step-by-Step
Approach
1. Declaration:
● Begin by declaring your exception in the declaration
section of your PL/SQL block, procedure, or function
using the EXCEPTION keyword.
MY_EXCEPTION EXCEPTION;
2. Raising the Exception:
● Within the execution section, you can raise the
exception based on a specific condition using the
RAISE statement.
IF some_condition THEN RAISE MY_EXCEPTION; END IF;
3. Handling the Exception:
● In the exception-handling section of your PL/SQL
block, you can specify the actions to be undertaken
once your exception is raised.
EXCEPTION WHEN MY_EXCEPTION THEN -- handle the
exception (e.g., log the error, notify the user)
5.3 Exception Handling
1. The Need for Effective Exception Handling
Exception handling is a pivotal aspect of robust and resilient
software design, especially in SQL programming. In the world of
data, where precision, accuracy, and reliability are paramount,
exceptions—unexpected events during the execution of a
program—can derail expected outcomes or even crash systems.
These can arise from various reasons:
● Unanticipated data inputs
● Data corruption
● Resource unavailability
● System malfunctions
Effective exception handling ensures that these unforeseen
events are captured and addressed systematically, thereby:
● Preserving the integrity of the system.
● Ensuring smooth user experience by preventing abrupt
failures.
● Facilitating easier debugging and problem resolution.
2. The PL/SQL Exception Handling Mechanism
PL/SQL, Oracle's procedural language extension to SQL,
integrates a rich exception handling mechanism. This is centred
around defining, raising, and handling exceptions in the
programmatic flow.
● Predefined exceptions: PL/SQL provides a set of
exceptions that are automatically raised when
corresponding errors occur. For example, ZERO_DIVIDE is
raised when a division-by-zero occurs.
● User-defined exceptions: Users can define and name
their own exceptions to capture specific error conditions.
3. Using BEGIN... EXCEPTION... END Blocks
The foundation of PL/SQL's exception handling lies in the
BEGIN... EXCEPTION... END blocks. This structure is
instrumental in defining the normal flow and specifying how to
handle deviations:
BEGIN -- Normal execution code here EXCEPTION WHEN
exception THEN -- Error handling code for exception WHEN
exception THEN -- Error handling code for exception2 ... END;
Within this block:
● The BEGIN section contains the main PL/SQL code.
● The EXCEPTION section is where specific exceptions are
captured and handled.
4. The RAISE and RAISE_APPLICATION_ERROR Procedures
● RAISE: This procedure allows manual triggering of an
exception. It's especially useful for user-defined
exceptions or in scenarios where a predefined exception
needs to be triggered based on custom logic.
Example:
DECLARE
my_exception EXCEPTION;
BEGIN
IF some_condition THEN
RAISE my_exception;
END IF;
EXCEPTION
WHEN my_exception THEN
-- Handle the exception
END;
● RAISE_APPLICATION_ERROR: A powerful built-in
procedure that allows raising a user-defined error with a
custom error message and error number. It's particularly
beneficial when standard exceptions do not adequately
describe an error scenario.
Example:
BEGIN
IF some_condition THEN
RAISE_APPLICATION_ERROR(-20001, 'An error occurred due
to some_condition');
END IF;
END;
5. Guidelines for Efficient Exception Management
For maintaining robustness and clarity in SQL programming,
consider these best practices:
● Be specific: Handle exceptions as specifically as possible.
Avoid generic catch-alls that can mask the true nature of
an issue.
● Provide meaningful feedback: Whether logging the error
or informing the user, ensure that the feedback is
descriptive to facilitate quicker resolution.
● Avoid overuse: While exceptions are powerful, they
should not be a replacement for proper control flow or
validation. Use them judiciously.
● Document: Any user-defined exception or unique
handling scenario should be well-documented for the
benefit of developers and maintenance teams.
● Centralise handling: If possible, centralise exception
handling to avoid repetitive code and ensure uniform
responses to exceptions.
5.4 Introduction to Triggers
Triggers are specialised routines that are set into motion (or
"triggered") when specific events occur within a relational
database system. These events can include insertions, deletions,
and updates. Unlike regular processes, which require explicit
calls, triggers automatically spring into action when their
defined events happen.
● How they work: Triggers watch for particular changes,
then automatically initiate defined operations when those
changes occur.
● Components:
o Event: What prompts the trigger. Common events
include INSERT, UPDATE, and DELETE operations.
o Condition: An optional specification that must be
met for the trigger to run.
o Action: What the trigger does. This is typically a
series of SQL statements.
Why are Triggers Important?
The primary significance of triggers lies in their ability to ensure
data integrity, automate complex business rules, and manage
log audit trails.
● Data Integrity: By specifying certain constraints that the
built-in constraints can't enforce, triggers help maintain
the quality and accuracy of the data.
● Automated Business Rules: Triggers can help enforce
complex business rules that might be challenging or
inefficient to implement at the application layer.
● Audit Trails: They can automatically generate logs and
historical records whenever data changes, aiding in the
tracing and monitoring of database activity.
Comparing Triggers with Stored Procedures
Both triggers and stored procedures are database objects that
store a sequence of SQL statements. However, there are key
differences:
● Activation:
o Triggers: Automatically initiated by data
modification or database operations.
o Stored Procedures: Executed when explicitly called
by a user or application.
● Purpose:
o Triggers: Mainly used for maintaining data integrity
and enforcing business rules automatically.
o Stored Procedures: Typically used for encapsulating
and reusing a series of SQL statements, potentially
for complex operations.
● Control:
o Triggers: Less control for end-users, as they are
implicit and automatic.
o Stored Procedures: More control, as they can be
executed on-demand and can accept parameters for
versatile use.
Real-world Applications of Database Triggers
In practical scenarios, triggers can be crucial in various
operations:
● E-commerce: When a customer places an order, a trigger
can automatically update the inventory count.
● Banking: After a customer makes a transaction, a trigger
can automatically update both the sender's and the
receiver's account balances.
● CRM Systems: When a sales representative updates a
deal's status to 'closed-won', a trigger might generate an
invoice automatically.
● Auditing: In sensitive industries, triggers can log any
change to critical data, providing a trail of who changed
what and when.
5.5 Creating and Managing Triggers
Triggers, in database systems, particularly in Oracle's PL/SQL,
are sets of commands that automatically execute or fire in
response to certain events, such as data modifications. They
are immensely useful in implementing business rules, ensuring
data integrity, and maintaining audit logs.
Anatomy of a PL/SQL Trigger
A typical PL/SQL trigger has several components:
● Triggering Event: This specifies when the trigger should
fire. Common events include INSERT, UPDATE, and
DELETE.
● Trigger Type: Based on their timing:
o BEFORE: Executes before the triggering event.
o AFTER: Executes after the triggering event.
● Triggering Level: Defines the level at which the trigger
acts:
o ROW level: Fires once for every row affected.
o STATEMENT level: Fires once for the SQL statement.
● Trigger Body: The PL/SQL block containing the logic to be
executed when the trigger fires.
Steps to Create a Trigger in Oracle Database
1. Define the Triggering Event: Decide when the trigger
should execute. For instance, after an INSERT on a specific
table.
2. Choose the Trigger Type and Level: Determine whether
you want it to execute before or after the event, and at
which level.
3. Write the PL/SQL Code: Define the logic inside the trigger
body.
4. Use the CREATE TRIGGER Statement: The basic syntax is:
CREATE [OR REPLACE] TRIGGER trigger_name
[BEFORE | AFTER] [INSERT | UPDATE | DELETE]
ON table_name [FOR EACH ROW]
BEGIN
-- Trigger logic here
END;
Modifying, Disabling, and Dropping Triggers: Best Practices
● Modifying Triggers:
o Use the CREATE OR REPLACE TRIGGER statement. It
ensures that if the trigger exists, it is replaced;
otherwise, a new one is created.
o Test the modified trigger in a controlled
environment before deploying in production.
● Disabling Triggers:
o If you need to temporarily halt a trigger’s operation,
you can disable it using the ALTER TRIGGER
trigger_name DISABLE; command.
o Disabling a trigger is useful during bulk data
operations to improve performance.
● Dropping Triggers:
o To remove a trigger, use the DROP TRIGGER
trigger_name; command.
o Before dropping, ensure that there are no
dependencies or business processes that still require
it.
Performance Considerations When Working with Triggers
Triggers, while powerful, can significantly impact database
performance:
● Overhead: Each trigger introduces some overhead.
Especially for operations affecting many rows, ROW level
triggers can slow down the process considerably.
● Complex Logic: Triggers with extensive or complex logic
can result in increased execution time.
● Multiple Triggers: If multiple triggers are set on the same
event for a table, it can be challenging to predict the
order in which they will execute, potentially causing
unintended results.
● Nested Triggers: If triggers invoke operations that fire
other triggers, it can lead to a cascading effect, affecting
performance and predictability.
5.6 Trigger Types: Row, Statement, Before, After, Instead Of
Triggers in SQL are powerful tools that allow for automatic
actions or side effects to take place in response to certain
database operations.
1. Trigger Types:
● Row-level Trigger: This is activated for each row that an
INSERT, UPDATE, or DELETE operation affects. Thus, if a
SQL operation affects multiple rows, the row-level trigger
will be executed multiple times, once for each affected
row.
● Statement-level Trigger: Activated once for each INSERT,
UPDATE, or DELETE operation, regardless of how many
rows are affected. These triggers aren't concerned with
specific rows but rather the overarching operation.
● BEFORE Trigger: This is fired before the triggering SQL
statement is executed, providing an opportunity to check
or change data before it's committed.
● AFTER Trigger: Executed after the triggering SQL
statement has run. Useful for actions that depend on the
statement completing successfully.
● INSTEAD OF Trigger: Generally associated with views. It's
executed instead of the triggering SQL statement,
allowing for an alternative action.
2. Distinguishing Between Row-level and Statement-level
Triggers:
● Row-level:
o Focuses on individual rows.
o Typically used when we need to perform an action
on each row affected, such as updating a specific
field.
o Has access to the 'OLD' and 'NEW' aliases to
reference the state of the row before and after the
triggering statement.
● Statement-level:
o Concerned with the operation as a whole.
o Does not have access to individual row data from
the triggering statement.
o Useful for tasks like auditing or tracking bulk
operations.
3. Deciding When to Use BEFORE vs. AFTER Triggers:
● BEFORE:
● When you need to validate or modify data before
it's written to the database.
● To prevent certain operations from happening
under specific conditions.
● AFTER:
● When you need to perform follow-up actions that
depend on the SQL operation successfully
completing.
● For actions that don't need to interfere with or
modify the triggering SQL operation, such as logging
or notifications.
4. Understanding and Implementing INSTEAD OF Triggers:
● Functionality:
o As the name suggests, these triggers run instead of
the operation that activated them.
● Common Use Cases:
o Primarily used with views, which can't directly
handle INSERTs, UPDATEs, or DELETEs since they
don’t represent physical tables.
o Allow developers to define actions that should be
taken when someone tries to modify data via a view.
● Implementation:
o The trigger essentially redefines the operation. For
example, an INSTEAD OF INSERT trigger on a view
could translate the insert action into an appropriate
insert on the underlying tables.
5. Use Cases and Scenarios for Different Trigger Types:
● Row-level:
o Cascading updates or deletes, where a change to
one row necessitates changes in other related rows.
o Record-level auditing, where changes to individual
rows are tracked.
● Statement-level:
o Monitoring bulk operations on a table.
o Logging operations without the need to capture
row-specific details.
● BEFORE:
o Data validation.
o Data transformation before persistence.
● AFTER:
o Notifications, like sending an email after the
successful addition of a new user.
o Logging actions for auditing purposes.
● INSTEAD OF:
o Redefining operations on views.
o Ensuring the integrity of complex operations
spanning multiple tables.
5.7 Summary
❖ Exceptions are runtime errors in PL/SQL programs, and
they can be either predefined by the Oracle environment
or custom-defined by developers. They enable handling
unforeseen errors gracefully without abrupt program
termination.
❖ Predefined exceptions are built into PL/SQL and
correspond to common Oracle errors. User-defined
exceptions are custom error conditions specified by
developers to manage specific scenarios not covered by
predefined ones.
❖ Exception handling in PL/SQL uses BEGIN... EXCEPTION...
END blocks to capture and manage errors. It allows
developers to specify actions to take when an error
occurs, such as logging, notification, or alternative
execution paths.
❖ Triggers are specialised stored procedures that
automatically execute (or "fire") in response to specific
events in a database, like data modifications or schema
changes, enhancing data integrity and enforcing business
rules.
❖ Triggers can be created using the CREATE TRIGGER
statement in Oracle. Management includes modifying,
enabling, disabling, or dropping triggers based on the
evolving needs of the database application.
❖ Triggers can be categorised based on timing (BEFORE,
AFTER, or INSTEAD OF) and scope (row-level or
statement-level). The choice of trigger type depends on
the specific use case and desired effect in response to
database events.
5.8 Keywords
● Exception: In PL/SQL, an exception is a runtime error or
warning condition that interrupts the normal flow of
execution. Exceptions can be caused by external factors
or can be deliberately raised by the program itself. They
are critical for identifying and handling unexpected issues
during program execution.
● Predefined Exception: These are standard exceptions
provided by Oracle's PL/SQL language. For instance,
NO_DATA_FOUND is a predefined exception that gets
raised when a SELECT INTO statement returns no rows.
Another example is ZERO_DIVIDE, which occurs when a
program attempts to divide by zero.
● User-Defined Exception: As the name suggests, these are
custom exceptions defined by the developer. User-
defined exceptions are especially useful when one needs
to raise and catch exceptions specific to the business or
application logic.
● Trigger: A trigger in PL/SQL is a stored procedure that
automatically executes or fires in response to specific
events (like an INSERT, UPDATE, or DELETE operation) on
a particular table or view. They are useful for maintaining
database integrity, automating tasks, and implementing
business logic.
● Row-Level Trigger: This type of trigger fires once for each
row affected by the triggering statement. For example, if
an UPDATE statement modifies 10 rows, a row-level
trigger would be executed 10 times.
● Statement-Level Trigger: Contrary to the row-level trigger,
a statement-level trigger fires once for each SQL
statement, regardless of how many rows are affected. If
an UPDATE statement modifies 10 rows, a statement-
level trigger would be executed just once for the entire
operation.
5.9 Self-Assessment Questions
1. How can you differentiate between predefined and user-
defined exceptions in PL/SQL?
2. What is the primary purpose of the
RAISE_APPLICATION_ERROR procedure in exception
handling?
3. Which trigger type, either row-level or statement-level, is
invoked once for each row that meets the triggering event
criteria?
4. What are the key distinctions between BEFORE, AFTER,
and INSTEAD OF triggers in PL/SQL?
5. How would you manage the performance implications of
having multiple triggers in a database application?
5.10 Case Study
Title: Tokyo Metro Data Analytics
Introduction:
The Tokyo Metro system, one of the busiest in the world,
transports millions of passengers daily. As part of an initiative
to enhance customer experience and improve operational
efficiency, the metro's management decided to use SQL
programming to analyse vast amounts of data collected
through ticketing systems, sensors, and customer feedback.
Challenge:
With increasing ridership, Tokyo Metro was facing issues in
peak hour congestion, ticketing discrepancies, and
infrastructure wear and tear. Traditional methods of data
analysis were proving insufficient to pinpoint problem areas.
They needed a data-driven approach to predict congestion,
identify potential fare evaders, and understand the lifespan of
their infrastructure components.
Solution:
A team of data scientists was set up, and they began by
centralising the disparate data sources into an SQL database.
Using SQL queries, they segmented data based on stations,
times, and ticket types.
1. To address congestion, the team developed an SQL
algorithm to predict peak times at specific stations based
on historical data. This helped in optimising train
schedules and station staffing.
2. For fare evasion detection, they analysed patterns of
ticket purchases and used SQL to correlate them with
entry and exit logs. Anomalies in this data, such as a
passenger exiting a station without any entry record,
were flagged for further investigation.
3. To understand infrastructure wear, SQL queries compare
the age of infrastructure components, like escalators or
tracks, against maintenance records and breakdown
incidents. This provided insights into which components
were likely to need replacements or upgrades.
Outcome:
By leveraging SQL programming, Tokyo Metro was able to
make informed decisions leading to smoother operations,
reduced fare evasion, and timely infrastructure maintenance.
This case underscores the vital role of SQL in transforming raw
data into actionable insights.
Questions:
1. How did the data scientists centralise the disparate data
sources, and why was this step crucial for effective
analysis?
2. Based on the case study, how did SQL programming aid
Tokyo Metro in identifying potential fare evaders?
3. In terms of infrastructure maintenance, how did the use
of SQL queries help Tokyo Metro prioritise upgrades or
replacements?
5.11 References
1. "Oracle PL/SQL Programming" by Steven Feuerstein and
Bill Pribyl
2. "SQL: The Complete Reference" by James R. Groff, Paul N.
Weinberg, and Andrew J. Oppel
3. "Mastering Oracle PL/SQL: Practical Solutions" by Connor
McDonald, Chaim Katz, Christopher Beck, and Joel R.
Kallman
4. "Pro Oracle Application Express" by John Scott and Scott
Spendolini
5. "Oracle Database 12c PL/SQL Programming" by Michael
McLaughlin