0% found this document useful (0 votes)
2 views

Dbms All Module Reviewer

The document covers PL/SQL programming, focusing on SQL statements, data manipulation, control structures, and exception handling. It explains how to interact with Oracle DB using SQL, including SELECT, INSERT, UPDATE, DELETE commands, and the use of cursors and records. Additionally, it details error handling mechanisms and the structure of PL/SQL programs, including loops and conditional statements.

Uploaded by

202310363
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Dbms All Module Reviewer

The document covers PL/SQL programming, focusing on SQL statements, data manipulation, control structures, and exception handling. It explains how to interact with Oracle DB using SQL, including SELECT, INSERT, UPDATE, DELETE commands, and the use of cursors and records. Additionally, it details error handling mechanisms and the structure of PL/SQL programs, including loops and conditional statements.

Uploaded by

202310363
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 27

Module 1: Interacting with Oracle DB Server and Control Structures

SQL Statements in PL/SQL Retrieving Data Using SELECT Statements


Types of SQL Statements Using the INTO Clause
SELECT: Retrieves data from a database. The INTO clause is mandatory when using
DML (Data Manipulation Language) statements SELECT in PL/SQL.
(to modify database records.): It stores retrieved data into a PL/SQL variable.
INSERT: Adds new records.
UPDATE: Modifies existing records. ex. retrieving an employee’s last name
DELETE: Removes records.
MERGE: Inserts or updates records based on DECLARE
conditions. v_emp_lname employees.last_name%TYPE;

ex. Insert Employee Data ex. Deleting Employees from BEGIN


DECLARE Department 10 SELECT last_name INTO v_emp_lname
v_sal_increase NUMBER := 800;
DECLARE FROM employees
BEGIN v_deptno NUMBER := 10; WHERE employee_id = 100;
UPDATE copy_emp BEGIN
SET salary = salary + v_sal_increase DELETE FROM copy_emp DBMS_OUTPUT.PUT_LINE('Last name: ' ||
WHERE job_id = 'ST_CLERK'; WHERE department_id = v_deptno; v_emp_lname);
END; END;
END;

ex. Updating Employee Salary


DECLARE
v_sal_increase NUMBER := 800;
Handling Errors in SELECT Statements
BEGIN
UPDATE copy_emp If the query returns more than one row, it raises
SET salary = salary + v_sal_increase
WHERE job_id = 'ST_CLERK'; ORA-01422: exact fetch returns more than
END; requested number of rows.
If no rows are returned, it raises a
Transaction control statements NO_DATA_FOUND exception.
(to manage transactions.)
COMMIT ex. summing Salaries of a Department
ROLLBACK DECLARE
SAVEPOINT v_sum_sal NUMBER(10,2);
v_deptno NUMBER := 60;
DDL/DCL Limitations
^^ cannot be directly executed in PL/SQL BEGIN
DDL (Data Definition Language) SELECT SUM(salary) INTO v_sum_sal
CREATE FROM employees
ALTER WHERE department_id = v_deptno;
DROP) DBMS_OUTPUT.PUT_LINE('Total Salary: ' ||
DCL (Data Control Language) v_sum_sal);
GRANT END;
REVOKE)
Use Dynamic SQL (EXECUTE IMMEDIATE) to
execute them at runtime. Data Manipulation Using PL/SQL
If the query returns more than one row, it raises
ORA-01422: exact fetch returns more than
Cursors in PL/SQL requested number of rows.
If no rows are returned, it raises a
Implicit Cursors NO_DATA_FOUND exception.
Created automatically for SQL statements
executed in PL/SQL. ex. summing Salaries of a Department
Cursor attributes:
SQL%FOUND: Returns TRUE if the last SQL DECLARE
statement affected at least one row. v_sum_sal NUMBER(10,2);
SQL%NOTFOUND: Returns TRUE if no rows v_deptno NUMBER := 60;
were affected.
SQL%ROWCOUNT: Returns the number of BEGIN
rows affected by the last SQL statement. SELECT SUM(salary) INTO v_sum_sal
FROM employees
ex. Using SQL%ROWCOUNT WHERE department_id = v_deptno;
DBMS_OUTPUT.PUT_LINE('Total Salary: ' ||
DECLARE
v_sum_sal);
v_deptno NUMBER := 50;
END;
BEGIN
DELETE FROM copy_emp WHERE
department_id = v_deptno;

DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT
|| ' rows deleted.');
END;

Control Structures in PL/SQL


IF Statements CASE Statements
Used for conditional execution of code. Used to simplify multiple conditional checks.
DECLARE
DECLARE
v_num NUMBER := 15;
v_myage NUMBER := 31; v_txt VARCHAR2(50);
BEGIN BEGIN
IF v_myage < 11 THEN CASE v_num
WHEN 20 THEN v_txt := 'number
DBMS_OUTPUT.PUT_LINE('I equals 20';
am a child'); WHEN 15 THEN v_txt := 'number equals
END IF; 15';
END; ELSE v_txt := 'some other number';
END CASE;
DBMS_OUTPUT.PUT_LINE(v_txt);
END;

reviewer by ina b <3


Loops in PL/SQL
Basic Loop WHILE Loop
Executes a block of code repeatedly until explicitly Repeats code while a condition remains TRUE.
terminated.
DECLARE DECLARE
v_counter NUMBER := 1; v_counter NUMBER := 1;
BEGIN BEGIN
LOOP WHILE v_counter <= 3 LOOP
DBMS_OUTPUT.PUT_LINE('Loop execution #' || DBMS_OUTPUT.PUT_LINE('Iteration: ' ||
v_counter); v_counter);
v_counter := v_counter + 1; v_counter := v_counter + 1;
EXIT WHEN v_counter > 5; END LOOP;
END LOOP; END;
END;

FOR Loop Nested Loops


Used for a known number of iterations. BEGIN
FOR v_outerloop IN 1..3 LOOP
BEGIN FOR v_innerloop IN 1..2 LOOP
FOR i IN 1..3 LOOP DBMS_OUTPUT.PUT_LINE('Outer: ' ||
DBMS_OUTPUT.PUT_LINE('Iteration: ' || i); v_outerloop || ', Inner: ' || v_innerloop);
END LOOP; END LOOP;
END; END LOOP;
END;

Using Loop Labels


Labels help exit nested loops efficiently.
DECLARE
v_outer_done CHAR(3) := 'NO';
BEGIN
<<outer_loop>>
LOOP
<<inner_loop>>
LOOP
EXIT outer_loop WHEN v_outer_done = 'YES';
EXIT inner_loop WHEN v_outer_done = 'YES';
END LOOP;
END LOOP;
END;

Module 1 Summary
SQL in PL/SQL:
SELECT, DML, transaction control.
Data Manipulation:
INSERT, UPDATE, DELETE, MERGE.
Cursors:
Implicit (SQL%FOUND, SQL%ROWCOUNT).
Control Structures:
IF, CASE, Loops (BASIC, WHILE, FOR,
Nested).
Loop Labels:
Help control nested loops.

reviewer by ina b <3


Module 2: Working with Composite Data Types
PL/SQL Records User-Defined PL/SQL Records
A PL/SQL record is a composite data type consisting of Creating Custom Records
multiple fields, each with its own name and data type. If you need a record structure that spans multiple
tables, use TYPE to define a user-defined record.
It allows grouping of related data items together as a single The record can include fields from multiple sources and
unit. custom attributes.

You can refer to: ex. Syntax for User-Defined Records


The entire record (record_name)
TYPE record_name IS RECORD (
Individual fields (record_name.field_name) field_name1 data_type,
field_name2 table_name.column_name%TYPE,
Declaring Records ...
%ROWTYPE allows creating a record that represents an );
entire row of a database table. variable_name record_name;
The structure of the record is based on the table’s
column names and data types. ex. User-Defined Record from Multiple Tables
ex. Declaring and Using a Record DECLARE
TYPE person_dept IS RECORD (
DECLARE first_name employees.first_name%TYPE,
v_emp_record employees%ROWTYPE; last_name employees.last_name%TYPE,
BEGIN department_name departments.department_name%TYPE
SELECT * INTO v_emp_record );
FROM employees v_person_dept_rec person_dept;
WHERE employee_id = 100; BEGIN
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || SELECT e.first_name, e.last_name, d.department_name
v_emp_record.first_name || ' ' || INTO v_person_dept_rec
v_emp_record.last_name); FROM employees e
END; JOIN departments d ON e.department_id =
d.department_id
Simplifies variable declaration. WHERE employee_id = 200;
DBMS_OUTPUT.PUT_LINE(v_person_dept_rec.first_name
Automatically adapts if table structure changes (e.g., || ' works in ' || v_person_dept_rec.department_name);
new columns added). END;
Reduces maintenance effort.
Scope and Visibility of Records
Implicit vs. Explicit Cursors Records can be declared in:
Implicit Cursors Anonymous blocks
Automatically created for SELECT statements that Procedures & functions
return a single row and DML (INSERT, UPDATE, Package specifications (global scope)
DELETE). Package bodies (local scope)
Cursor attributes:
%FOUND: TRUE if the last SQL statement affected ex. Nested Scope of Records
rows. DECLARE -- Outer Block
%NOTFOUND: TRUE if no rows were affected. TYPE employee_type IS RECORD (
%ROWCOUNT: Returns the number of rows first_name employees.first_name%TYPE
affected. );
v_emp_rec_outer employee_type;
Explicit Cursors BEGIN
Used when a query returns multiple rows. v_emp_rec_outer.first_name := 'Amy';
DBMS_OUTPUT.PUT_LINE(v_emp_rec_outer.first_name);
Must be manually declared, opened, fetched, and closed.
DECLARE -- Inner Block
Steps for Using an Explicit Cursor v_emp_rec_inner employee_type;
Declare the Cursor (Define the SQL statement). BEGIN
Open the Cursor (Execute the SQL query). v_emp_rec_outer.first_name := 'Clara';
Fetch Data (Retrieve each row one at a time). DBMS_OUTPUT.PUT_LINE(v_emp_rec_outer.first_name);
Close the Cursor (Release resources). END;
END;
ex. Fetching Multiple Rows with an Explicit Cursor
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name FROM employees WHERE
department_id = 50;
v_empno employees.employee_id%TYPE;
v_lname employees.last_name%TYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_empno, v_lname;
EXIT WHEN cur_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_lname);
END LOOP;
CLOSE cur_emps; Module 2 Summary
END; PL/SQL Records:
%ROWTYPE provides a convenient way to define a record
structure based on a table.
ex. Cursor FOR Loop (Simplified Explicit Cursor) User-defined records allow custom structures spanning
DECLARE multiple tables.
CURSOR cur_emps IS Cursors:
Implicit cursors handle single-row queries automatically.
SELECT employee_id, last_name FROM employees WHERE Explicit cursors provide fine-grained control over multi-row
department_id = 50; queries.
BEGIN Cursor FOR loops simplify explicit cursor usage.
FOR v_emp_rec IN cur_emps LOOP Cursor Attributes:
DBMS_OUTPUT.PUT_LINE(v_emp_rec.employee_id || ' ' || %FOUND, %NOTFOUND, %ROWCOUNT, %ISOPEN help
v_emp_rec.last_name); manage cursor operations.
END LOOP;
END;

reviewer by ina b <3


Module 3: PL/SQL Exceptions
What is an Exception? Exception Handling in PL/SQL
An exception occurs when an error disrupts the normal An Exception Handler is code that handles errors and
execution of a program. defines recovery actions.
Common Causes: Types of Errors to Handle:
Incorrect user input (e.g., wrong password). System Errors (e.g., full disk space).
Incorrect SQL queries (e.g., missing table/column). Data Errors (e.g., duplicate primary key).
Invalid data entry (e.g., past expiration date). User Action Errors (e.g., incorrect input).
SQL query returning unexpected results (e.g., no rows,
multiple rows). Exception Handler Syntax
ex. “No_Data_Found” Exception EXCEPTION
WHEN exception_name THEN
DECLARE statement;
v_country_name countries.country_name%TYPE := 'Korea, WHEN exception_name2 THEN
South'; statement;
v_elevation countries.highest_elevation%TYPE; WHEN OTHERS THEN
BEGIN statement; -- Handles all other exceptions
SELECT highest_elevation INTO v_elevation
FROM countries
WHERE country_name = v_country_name; ex. Handling “No_Data_Found” Exception
END; DECLARE

❌ No data found" (because the correct country name v_country_name countries.country_name%TYPE := 'Korea, South';
v_elevation countries.highest_elevation%TYPE;
is "Republic of Korea"). BEGIN
SELECT highest_elevation INTO v_elevation
FROM countries WHERE country_name = v_country_name;

EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Country name ' || v_country_name || ' not
found.');
END;

✅ Handled Error Message: "Country name Korea, South not


found."
Types of Exceptions in PL/SQL
Predefined Oracle Server Errors User-Defined Exceptions
Errors automatically recognized by Oracle. Errors created by the programmer for custom
Examples: validation.
NO_DATA_FOUND → No matching rows in SELECT Steps to Implement:
query. 1. Declare the exception name.
TOO_MANY_ROWS → SELECT returned multiple 2. Use RAISE to trigger the exception.
rows instead of one. 3. Handle it in the EXCEPTION section.
ZERO_DIVIDE → Division by zero.
INVALID_CURSOR → Invalid cursor operation. ex. Handling Invalid Department ID
DUP_VAL_ON_INDEX → Attempt to insert a DECLARE
duplicate unique key. e_invalid_department EXCEPTION;
v_name VARCHAR2(20) := 'Accounting';
ex. “Too_Many_Rows” Exception v_deptno NUMBER := 27;
DECLARE BEGIN
v_lname VARCHAR2(15); UPDATE departments
BEGIN SET department_name = v_name
SELECT last_name INTO v_lname WHERE department_id = v_deptno;
FROM employees WHERE job_id = 'ST_CLERK';
IF SQL%NOTFOUND THEN
EXCEPTION RAISE e_invalid_department;
WHEN TOO_MANY_ROWS THEN END IF;
DBMS_OUTPUT.PUT_LINE('Your select statement retrieved
multiple rows.'); EXCEPTION
END; WHEN e_invalid_department THEN
DBMS_OUTPUT.PUT_LINE('No such department ID.');
✅ Handled Error Message: "Your select statement END;

retrieved multiple rows." ✅ Handled Error Message: "No such department ID."
The RAISE_APPLICATION_ERROR Procedure
Non-Predefined Oracle Server Errors
Use Case: Assign custom error messages with error
Oracle errors without a predefined name.
codes.
Solution: Use PRAGMA EXCEPTION_INIT to assign a
name.
RAISE_APPLICATION_ERROR Procedure Syntax
ex. Handling ORA-01400 (NULL Value Insert) RAISE_APPLICATION_ERROR(error_number, message
DECLARE [, {TRUE | FALSE}]);
e_insert_excep EXCEPTION;
PRAGMA EXCEPTION_INIT(e_insert_excep, -1400); error_number: Between -20000 and -20999 (reserved
BEGIN for user-defined errors).
INSERT INTO departments (department_id, department_name) message: Custom error message (max 2048 bytes).
VALUES (280, NULL);
TRUE | FALSE:
EXCEPTION TRUE → Keeps previous errors.
WHEN e_insert_excep THEN FALSE (default) → Replaces previous errors.
DBMS_OUTPUT.PUT_LINE('INSERT FAILED: Cannot insert
NULL.');
END;

✅ Handled Error Message: "INSERT FAILED: Cannot


insert NULL."

reviewer by ina b <3


The RAISE_APPLICATION_ERROR Procedure Functions for Trapping Exceptions
Use Case: Assign custom error messages with error SQLCODE: Returns error number.
codes. SQLERRM: Returns error message.

RAISE_APPLICATION_ERROR Procedure Syntax ex. Logging Errors in a Table


RAISE_APPLICATION_ERROR(error_number, message DECLARE
[, {TRUE | FALSE}]); v_error_code NUMBER;
v_error_message VARCHAR2(255);
error_number: Between -20000 and -20999 BEGIN
(reserved for user-defined errors). -- Some operation that causes an error
message: Custom error message (max 2048 bytes). EXCEPTION
WHEN OTHERS THEN
TRUE | FALSE: v_error_code := SQLCODE;
TRUE → Keeps previous errors. v_error_message := SQLERRM;
FALSE (default) → Replaces previous errors.
INSERT INTO error_log (e_user, e_date, error_code,
error_message)
ex. Using RAISE_APPLICATION_ERROR VALUES (USER, SYSDATE, v_error_code, v_error_message);
END;
DECLARE
v_mgr PLS_INTEGER := 123;
BEGIN ✅ Stores the error in the error_log table.
DELETE FROM employees WHERE manager_id = v_mgr;

IF SQL%NOTFOUND THEN Exception Propagation in Nested Blocks


RAISE_APPLICATION_ERROR(-20202, 'This is not a valid If an exception is not handled inside a block, it
manager'); propagates to the enclosing block.
END IF; Best Practice: Handle exceptions at the appropriate
END; level.
✅ Handled Error Message: "This is not a valid ex. Exception Propagation
manager."
BEGIN
BEGIN
RAISE NO_DATA_FOUND; -- Inner block exception
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Inner: Too many rows');
END;

DBMS_OUTPUT.PUT_LINE('Outer: Still running');

EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Outer: No data found');
END;

✅ Handled at the outer level if not caught inside the


inner block.

Module 3 Summary
Always handle exceptions to prevent program crashes.
Use named exceptions (NO_DATA_FOUND, TOO_MANY_ROWS) when possible.
Define user exceptions for business rules.
Use RAISE_APPLICATION_ERROR for meaningful error messages.
Use SQLCODE & SQLERRM for debugging.

reviewer by ina b <3


Module 4: PL/SQL Procedures
What is a Procedure? What Are Parameters?
A procedure is a named PL/SQL block that performs a Parameters are placeholders for values that are passed
specific action but does not necessarily return a value. when calling a procedure.
They allow dynamic execution instead of hardcoding values.
Procedures modularize code, making programs easier to
understand, reuse, and maintain.

Key Concepts of Procedures


Encapsulation: Procedures group related operations into
a single unit.
Reusability: Procedures can be called multiple times to
execute the same logic. Working with Parameters
Abstraction: Hides implementation details, allowing IN Parameters (Read-Only)
users to call it without knowing internal workings. Default mode
Security: Restricts access to underlying tables via can pass values but cannot be modified inside the
controlled execution. procedure.
Performance: Precompiled and stored in database
memory, reducing execution time. Example: Using IN Parameters
CREATE OR REPLACE PROCEDURE greet_user (p_name IN
VARCHAR2) IS
Anonymous Blocks vs. Subprograms BEGIN
PL/SQL blocks can be anonymous or named subprograms DBMS_OUTPUT.PUT_LINE('Hello, ' || p_name || '!');
(procedures and functions). END;

Calling it:
BEGIN
greet_user('Alice');
END;

✅ Output: Hello, Alice!


OUT Parameters (Write-Only)
Used to return a value.
The value must be set inside the procedure before
returning.
Example: Using OUT Parameters
CREATE OR REPLACE PROCEDURE get_salary (
p_emp_id IN employees.employee_id%TYPE,
p_salary OUT NUMBER
Syntax of a Procedure
) IS
CREATE [OR REPLACE] PROCEDURE procedure_name BEGIN
[(parameter1 [mode] datatype1, parameter2 [mode] datatype2, ...)] SELECT salary INTO p_salary FROM employees WHERE
IS|AS employee_id = p_emp_id;
-- Declarations (Optional) END;
BEGIN
-- Executable statements Calling it:
EXCEPTION
DECLARE
WHEN OTHERS THEN
v_salary NUMBER;
-- Exception handling
BEGIN
END procedure_name;
get_salary(101, v_salary);
ex. Simple Procedure DBMS_OUTPUT.PUT_LINE('Salary: ' || v_salary);
END;
CREATE OR REPLACE PROCEDURE say_hello IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello, PL/SQL!');
✅ Output: Salary: 6000
END say_hello;
IN OUT Parameters (Read & Write)
Used when both input & output are required.
Parameter Passing Methods Can modify and return the value.
Example: Using IN OUT Parameters
CREATE OR REPLACE PROCEDURE double_salary (p_salary IN
OUT NUMBER) IS
BEGIN
p_salary := p_salary * 2;
END;
Calling it:
DECLARE
v_salary NUMBER := 5000;
BEGIN
double_salary(v_salary);
DBMS_OUTPUT.PUT_LINE('Doubled Salary: ' || v_salary);
END;

✅ Output: Doubled Salary: 10000

reviewer by ina b <3


Default Parameter Values Error Handling in Procedures
Use DEFAULT or := to provide default values. Use EXCEPTION blocks to handle errors.
Use SQLCODE & SQLERRM to capture error details.
ex. Default Parameter Values
CREATE OR REPLACE PROCEDURE welcome_user ( ex. Exception Handling in Procedures
p_name IN VARCHAR2 DEFAULT 'Guest'
CREATE OR REPLACE PROCEDURE find_salary (
) IS
p_emp_id IN employees.employee_id%TYPE,
BEGIN
p_salary OUT NUMBER
DBMS_OUTPUT.PUT_LINE('Welcome, ' || p_name || '!');
) IS
END;
BEGIN
Calling it: SELECT salary INTO p_salary FROM employees WHERE
BEGIN employee_id = p_emp_id;
welcome_user; -- Uses default 'Guest' EXCEPTION
welcome_user('Alice'); -- Uses 'Alice' WHEN NO_DATA_FOUND THEN
END; DBMS_OUTPUT.PUT_LINE('Error: No employee found!');

✅ Output: WHEN OTHERS THEN


DBMS_OUTPUT.PUT_LINE('Unexpected error: ' || SQLERRM);
Welcome, Guest! END;
Welcome, Alice!
Calling it:
Local Subprograms (Nested Procedures) DECLARE
v_salary NUMBER;
Used when a procedure is only needed inside another BEGIN
procedure. find_salary(999, v_salary);
END;
ex. Nested Procedures
Output: Error: No employee found!
CREATE OR REPLACE PROCEDURE delete_employee (
p_emp_id IN employees.employee_id%TYPE
) IS
PROCEDURE log_deletion (p_id IN employees.employee_id%TYPE)
IS
BEGIN
INSERT INTO employee_log VALUES (p_id, SYSDATE);
END log_deletion;
BEGIN
DELETE FROM employees WHERE employee_id = p_emp_id;
log_deletion(p_emp_id);
END;

Module 4 Summary
Procedures modularize code and improve security.
Can accept IN, OUT, and IN OUT parameters.
Exception handling ensures robustness.
Positional, Named, and Mixed parameter passing allow flexibility.
Local subprograms improve modularity inside procedures.

reviewer by ina b <3


Module 5: PL/SQL Functions
What is a Stored Function? Function Example: Retrieving Employee Salary
A function is a named PL/SQL block (subprogram) that:
Accepts optional IN parameters. ex. Function with a Parameter
Returns exactly one value. CREATE OR REPLACE FUNCTION get_sal
Must be called as part of a SQL or PL/SQL expression. (p_id IN employees.employee_id%TYPE)
In PL/SQL expressions, a function behaves like a RETURN NUMBER IS
variable, with a value determined by its parameters. v_sal employees.salary%TYPE := 0;
A function must have: BEGIN
A RETURN clause in the header. SELECT salary INTO v_sal FROM employees WHERE employee_id
At least one RETURN statement in the executable = p_id;
section. RETURN v_sal;
END get_sal;
Syntax of a Function
CREATE [OR REPLACE] FUNCTION function_name Invocation Example
[(parameter1 [mode1] datatype1, ...)]
RETURN datatype IS|AS DECLARE v_salary NUMBER;
[local_variable_declarations; …] BEGIN
BEGIN v_salary := get_sal(100); -- Calls the function
-- actions; END;
RETURN expression;
END [function_name];
Using RETURN Statements
Key Components:
Functions must include a RETURN statement that
CREATE OR REPLACE FUNCTION → Defines the function.
provides the output value.
RETURN datatype → Specifies the return type. RETURN can also be used in the EXCEPTION section.
BEGIN...END → Contains the function logic.
RETURN expression; → Ensures the function returns a single ex. Function with Exception Handling
value. CREATE OR REPLACE FUNCTION get_sal
(p_id IN employees.employee_id%TYPE)
Ways to Invoke Functions RETURN NUMBER IS
v_sal employees.salary%TYPE := 0;
1 . As Part of a PL/SQL Expression BEGIN
DECLARE v_sal employees.salary%TYPE; SELECT salary INTO v_sal FROM employees WHERE employee_id
BEGIN = p_id;
v_sal := get_sal(100); RETURN v_sal;
END; EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
2 . As a Parameter in Another Subprogram END get_sal;

BEGIN Invocation Example


DBMS_OUTPUT.PUT_LINE(get_sal(100));
DECLARE v_salary NUMBER;
END;
BEGIN
v_salary := get_sal(999); -- Invalid ID returns NULL
3 . As an Expression in a SQL Statement END;
SELECT job_id, get_sal(employee_id) FROM employees;

Restrictions: Functions used in SQL statements must NOT: Functions Without Parameters
Contain DML (INSERT, UPDATE, DELETE). Some built-in functions like USER and SYSDATE do not
Use COMMIT or ROLLBACK. require parameters.
Modify global variables.
ex. Assigning SYSDATE to a Variable
Benefits & Restrictions of Functions DECLARE v_today DATE;
BEGIN
Benefits v_today := SYSDATE;
Allows for quick calculations in SQL queries. END;
Extends SQL functionality with custom processing.
Can encapsulate reusable logic. ex. Using a Function in a SQL Statement
Restrictions SELECT job_id, SYSDATE - hire_date FROM employees;
PL/SQL types do not fully align with SQL types (e.g.,
BOOLEAN is not valid in SQL).
Size differences exist between PL/SQL and SQL Choosing Between a Procedure and a Function
(VARCHAR2 in PL/SQL can be 32KB, but in SQL, it's
only 4KB). Use a Function when:
You need a return value in a query.
Differences Between Procedures and Functions The function does not modify data (e.g., computing
salaries, validating input).
Use a Procedure when:
You need to execute multiple actions (e.g.,
inserting/updating records).
A return value is not necessary.

Module 5 Summary
1. Functions must return exactly one value.
2. Functions are invoked in expressions, SQL statements, or subprograms.
3. Functions cannot perform DML when used in SQL statements.
4. Syntax structure:
a. CREATE FUNCTION function_name RETURN datatype
b. RETURN statement is mandatory.
5. Procedures vs. Functions:
a. Functions must return a value.
b. Procedures may or may not return a value.
c. Functions must have at least one RETURN statement.

reviewer by ina b <3


Module 6: Creating Packages
What Are PL/SQL Packages? Components of a PL/SQL Package
A PL/SQL package is a collection of related: A package consists of two parts, stored separately in the
Procedures Constants database:
Functions Cursors Package Specification (Public Interface)
Variables Exceptions Declares the constructs (procedures, functions,
variables, cursors, and exceptions) that are visible to
Packages allow modular programming by grouping related other PL/SQL blocks.
PL/SQL subprograms in a structured way. Must be created first before the package body.
Example Use Case:
A Human Resources package might include: Package Body (Implementation)
Procedures for hiring and firing employees. Contains the actual code for the subprograms declared
Functions to calculate commissions and bonuses. in the specification.
Variables for tax exemptions. May also contain private variables, procedures, and
functions.
Benefits of Using Packages The package body can be edited and recompiled without
Encapsulation: Implementation details are hidden from modifying the specification, allowing for flexible
users. updates.
Modularity: Groups related subprograms together.
Reusability: Code can be easily reused in multiple Syntax for Creating a Package Specification
applications. CREATE [OR REPLACE] PACKAGE package_name
Performance: Reduces recompilation time and increases IS
efficiency. -- Public type and variable declarations
-- Public subprogram specifications
Package Visibility: Public vs. Private Constructs END [package_name];
Public Constructs
Declared in the package specification. Accessible from Example Package Specification
outside the package. CREATE OR REPLACE PACKAGE check_emp_pkg
IS
Private Constructs g_max_length_of_service CONSTANT NUMBER := 100;
Declared only in the package body. Cannot be accessed
from outside the package.
PROCEDURE chk_hiredate(p_date IN
Example of a Private Procedure employees.hire_date%TYPE);
PROCEDURE chk_dept_mgr(p_empid IN
CREATE OR REPLACE PACKAGE BODY check_emp_pkg
IS employees.employee_id%TYPE,
PROCEDURE private_proc IS p_mgr IN employees.manager_id%TYPE);
BEGIN END check_emp_pkg;
DBMS_OUTPUT.PUT_LINE('This is a private procedure');
END private_proc; g_max_length_of_service → A public constant.
END check_emp_pkg; chk_hiredate → A procedure to validate an employee’s hire date.
chk_dept_mgr → A procedure to verify a department manager.
private_proc cannot be called outside of check_emp_pkg.

Syntax for Creating a Package Body


Invoking Package Subprograms CREATE [OR REPLACE] PACKAGE BODY package_name
Calling a Subprogram from the Same Package IS
Inside the package, just use the subprogram name: -- Private type and variable declarations
-- Subprogram bodies
chk_hiredate(SYSDATE); [BEGIN initialization statements]
END [package_name];
Calling a Subprogram Externally Example: Package Body
Use the fully qualified name:
CREATE OR REPLACE PACKAGE BODY check_emp_pkg
BEGIN IS
check_emp_pkg.chk_hiredate(SYSDATE); PROCEDURE chk_hiredate(p_date IN
END;
employees.hire_date%TYPE)
This ensures that the correct package is referenced. IS
BEGIN
Modifying a Package IF MONTHS_BETWEEN(SYSDATE, p_date) >
Updating the Package Body Without Changing the g_max_length_of_service * 12 THEN
Specification RAISE_APPLICATION_ERROR(-20200, 'Invalid Hiredate');
The package body can be recompiled without recompiling END IF;
the specification. END chk_hiredate;
This allows for updates without breaking existing
applications. PROCEDURE chk_dept_mgr(p_empid IN
ex. Changing an Error Message employees.employee_id%TYPE,
p_mgr IN employees.manager_id%TYPE)
CREATE OR REPLACE PACKAGE BODY check_emp_pkg
IS IS
PROCEDURE chk_hiredate(p_date IN BEGIN
employees.hire_date%TYPE) -- Implementation code here
IS END chk_dept_mgr;
BEGIN
END check_emp_pkg;
IF MONTHS_BETWEEN(SYSDATE, p_date) >
g_max_length_of_service * 12 THEN The procedures are now fully implemented within the package
RAISE_APPLICATION_ERROR(-20201, 'Hiredate Too Old');
body.
END IF;
END chk_hiredate; RAISE_APPLICATION_ERROR is used to throw an error if the
END check_emp_pkg; hire date exceeds the max service limit.
The package body must include the subprograms declared in
The error message has changed from "Invalid the package specification.
Hiredate" to "Hiredate Too Old" without affecting
other parts of the package.

reviewer by ina b <3


Module 6: Creating Packages
Removing a Package Describing a Package
To drop the entire package (specification and body): To view the structure of a package, use:
DROP PACKAGE package_name; DESCRIBE check_emp_pkg;

This will show public subprograms and variables within


To drop only the package body (keeping the
the package.
specification):
DROP PACKAGE BODY package_name;

Important: You cannot remove only the package


specification; the body depends on it.

Reasons for Using Packages

Module 6 Summary
1. Packages group related PL/SQL subprograms, variables, cursors, and exceptions.
2. A package consists of a public specification (interface) and a private body
(implementation).
3. Public subprograms are declared in the package specification.
4. Private subprograms are declared in the package body and are not accessible
externally.
5. Package bodies can be recompiled independently of their specification.
6. Use package_name.subprogram_name to call a procedure or function from a
package.
7. Packages improve performance by reducing redundant loading and compilation.

reviewer by ina b <3


Module 6: Creating Packages
What Are PL/SQL Packages? Components of a PL/SQL Package
A PL/SQL package is a collection of related: A package consists of two parts, stored separately in the
Procedures Constants database:
Functions Cursors Package Specification (Public Interface)
Variables Exceptions Declares the constructs (procedures, functions,
variables, cursors, and exceptions) that are visible to
Packages allow modular programming by grouping related other PL/SQL blocks.
PL/SQL subprograms in a structured way. Must be created first before the package body.
Example Use Case:
A Human Resources package might include: Package Body (Implementation)
Procedures for hiring and firing employees. Contains the actual code for the subprograms declared
Functions to calculate commissions and bonuses. in the specification.
Variables for tax exemptions. May also contain private variables, procedures, and
functions.
Benefits of Using Packages The package body can be edited and recompiled without
Encapsulation: Implementation details are hidden from modifying the specification, allowing for flexible
users. updates.
Modularity: Groups related subprograms together.
Reusability: Code can be easily reused in multiple Syntax for Creating a Package Specification
applications. CREATE [OR REPLACE] PACKAGE package_name
Performance: Reduces recompilation time and increases IS
efficiency. -- Public type and variable declarations
-- Public subprogram specifications
Package Visibility: Public vs. Private Constructs END [package_name];
Public Constructs
Declared in the package specification. Accessible from Example Package Specification
outside the package. CREATE OR REPLACE PACKAGE check_emp_pkg
IS
Private Constructs g_max_length_of_service CONSTANT NUMBER := 100;
Declared only in the package body. Cannot be accessed
from outside the package.
PROCEDURE chk_hiredate(p_date IN
Example of a Private Procedure employees.hire_date%TYPE);
PROCEDURE chk_dept_mgr(p_empid IN
CREATE OR REPLACE PACKAGE BODY check_emp_pkg
IS employees.employee_id%TYPE,
PROCEDURE private_proc IS p_mgr IN employees.manager_id%TYPE);
BEGIN END check_emp_pkg;
DBMS_OUTPUT.PUT_LINE('This is a private procedure');
END private_proc; g_max_length_of_service → A public constant.
END check_emp_pkg; chk_hiredate → A procedure to validate an employee’s hire date.
chk_dept_mgr → A procedure to verify a department manager.
private_proc cannot be called outside of check_emp_pkg.

Syntax for Creating a Package Body


Invoking Package Subprograms CREATE [OR REPLACE] PACKAGE BODY package_name
Calling a Subprogram from the Same Package IS
Inside the package, just use the subprogram name: -- Private type and variable declarations
-- Subprogram bodies
chk_hiredate(SYSDATE); [BEGIN initialization statements]
END [package_name];
Calling a Subprogram Externally Example: Package Body
Use the fully qualified name:
CREATE OR REPLACE PACKAGE BODY check_emp_pkg
BEGIN IS
check_emp_pkg.chk_hiredate(SYSDATE); PROCEDURE chk_hiredate(p_date IN
END;
employees.hire_date%TYPE)
This ensures that the correct package is referenced. IS
BEGIN
Modifying a Package IF MONTHS_BETWEEN(SYSDATE, p_date) >
Updating the Package Body Without Changing the g_max_length_of_service * 12 THEN
Specification RAISE_APPLICATION_ERROR(-20200, 'Invalid Hiredate');
The package body can be recompiled without recompiling END IF;
the specification. END chk_hiredate;
This allows for updates without breaking existing
applications. PROCEDURE chk_dept_mgr(p_empid IN
ex. Changing an Error Message employees.employee_id%TYPE,
p_mgr IN employees.manager_id%TYPE)
CREATE OR REPLACE PACKAGE BODY check_emp_pkg
IS IS
PROCEDURE chk_hiredate(p_date IN BEGIN
employees.hire_date%TYPE) -- Implementation code here
IS END chk_dept_mgr;
BEGIN
END check_emp_pkg;
IF MONTHS_BETWEEN(SYSDATE, p_date) >
g_max_length_of_service * 12 THEN The procedures are now fully implemented within the package
RAISE_APPLICATION_ERROR(-20201, 'Hiredate Too Old');
body.
END IF;
END chk_hiredate; RAISE_APPLICATION_ERROR is used to throw an error if the
END check_emp_pkg; hire date exceeds the max service limit.
The package body must include the subprograms declared in
The error message has changed from "Invalid the package specification.
Hiredate" to "Hiredate Too Old" without affecting
other parts of the package.

reviewer by ina b <3


Module 7: Creating Triggers
What is a Trigger? Syntax and Examples of Triggers
A trigger is a PL/SQL block that is automatically
executed in response to a specific event in a database. Statement-Level Trigger (Fires Once per Statement)
CREATE OR REPLACE TRIGGER log_department_changes
Key Characteristics of Triggers AFTER INSERT OR UPDATE OR DELETE ON departments
BEGIN
Automatic Execution → Fires when a specified event INSERT INTO dept_log (user_id, log_time) VALUES (USER,
occurs (INSERT, UPDATE, DELETE, etc.). SYSDATE);
Associated with Tables, Views, or System Events → Can END;
be attached to a table, view, schema, or database. Fires after an INSERT, UPDATE, or DELETE on the
Stored in the Database → Just like procedures,
functions, and packages. departments table.
No Explicit Invocation → Unlike stored procedures, Inserts a record into dept_log only once, even if multiple
triggers cannot be called manually. rows were affected.

Why Use Triggers? Row-Level Trigger (Fires Once per Row)


Triggers automate tasks like: CREATE OR REPLACE TRIGGER log_salary_changes
Data Validation (e.g., preventing incorrect salary AFTER UPDATE OF salary ON employees
updates). FOR EACH ROW
Auditing and Logging (e.g., tracking login times). BEGIN
Complex Business Rules Enforcement (e.g., ensuring an INSERT INTO salary_log (employee_id, old_salary, new_salary,
employee doesn’t take the same job twice). change_time)
Security Enforcement (e.g., restricting table VALUES (:OLD.employee_id, :OLD.salary, :NEW.salary,
modifications). SYSDATE);
END;
Example: Logging Salary Changes Automatically :OLD.salary → The salary before the update.
Instead of manually calling a logging function, you can use a :NEW.salary → The new salary after the update.
trigger: Runs once for each row affected by the UPDATE statement
CREATE OR REPLACE TRIGGER log_salary_change
AFTER UPDATE OF salary ON employees Preventing Invalid Updates with a Trigger
BEGIN Example: Ensuring Employees Cannot Take the Same Job
INSERT INTO salary_log (user_id, change_time) VALUES
(USER, SYSDATE); Again
END;
CREATE OR REPLACE TRIGGER check_job_change
BEFORE UPDATE OF job_id ON employees
Types of Triggers in PL/SQL FOR EACH ROW
DECLARE
Triggers can be classified based on WHEN they fire and v_job_count INTEGER;
HOW MANY TIMES they execute. BEGIN
SELECT COUNT(*) INTO v_job_count FROM job_history
WHERE employee_id = :OLD.employee_id AND job_id =
:NEW.job_id;

IF v_job_count > 0 THEN


RAISE_APPLICATION_ERROR(-20201, 'This employee has
already held this job.');
END IF;
END;

Prevents employees from being assigned to a job they’ve


already held.
Uses RAISE_APPLICATION_ERROR to stop invalid updates

Managing Triggers: Enabling, Disabling, and Dropping

Disabling and Enabling a Trigger


Viewing Trigger Information
ALTER TRIGGER log_salary_changes DISABLE;
Triggers are stored in the Data Dictionary and can be ALTER TRIGGER log_salary_changes ENABLE;
queried using:
Use DISABLE to temporarily turn off the trigger.
Viewing All Triggers in Your Schema Use ENABLE to reactivate the trigger.

SELECT trigger_name, table_name, status FROM


USER_TRIGGERS;
Dropping (Deleting) a Trigger
DROP TRIGGER log_salary_changes;
Viewing the Source Code of a Trigger Permanently removes the trigger from the database.

SELECT trigger_body FROM USER_TRIGGERS


WHERE trigger_name = 'LOG_SALARY_CHANGES';

Advanced Concepts in Triggers


INSTEAD OF Triggers (For Views) Conditional Predicates in Triggers
Used when a view is not directly updatable (e.g., a view
based on a JOIN).
Example: Updating a Complex View Using an INSTEAD OF
Trigger
CREATE OR REPLACE TRIGGER update_emp_view
INSTEAD OF UPDATE ON emp_view
BEGIN
UPDATE employees SET salary = :NEW.salary WHERE
employee_id = :OLD.employee_id;
END;

reviewer by ina b <3


Conditional Predicates in Triggers Common Trigger Issues
Mutating Table Error
Occurs when a row trigger reads from the same table it
is modifying.
Fix: Use a statement-level trigger or store values in a
temporary table.

Performance Issues
Too many triggers can slow down transactions.
Example: Using Conditional Predicates Best Practice: Keep trigger logic short and efficient.
CREATE OR REPLACE TRIGGER restrict_salary_changes
BEFORE INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW
BEGIN
IF INSERTING THEN
RAISE_APPLICATION_ERROR(-20202, 'No new
employees can be added.');
ELSIF UPDATING THEN
RAISE_APPLICATION_ERROR(-20203, 'Employee
records cannot be changed.');
ELSIF DELETING THEN
RAISE_APPLICATION_ERROR(-20204, 'Employees
cannot be deleted.');
END IF;
END;

💡 Now, employees cannot be inserted, updated, or deleted!

Module 7 Summary

reviewer by ina b <3

You might also like