💻 Working with PL/SQL
PL/SQL (Procedural Language for SQL) is Oracle’s extension to SQL that adds programming features like variables, loops, conditions, cursors, and exception handling. It allows developers to write blocks of code that can interact with databases efficiently and securely.
📦 Generic PL/SQL Block Structure
A PL/SQL program is divided into logical sections called blocks. Each block may contain declarations, executable statements, and exception handling parts.
DECLARE
-- Declarations (variables, cursors, constants)
BEGIN
-- Executable statements (SQL and procedural logic)
EXCEPTION
-- Error handling section
END;
/
Explanation:
- DECLARE: Optional section to declare variables or cursors.
- BEGIN: Mandatory section that holds executable SQL and PL/SQL statements.
- EXCEPTION: Optional section that handles runtime errors.
- END: Marks the end of the block.
Example:
DECLARE
v_name VARCHAR2(30) := 'Saksham';
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello ' || v_name);
END;
/
✅ Output: Hello Saksham
🔁 SQL Transactions in PL/SQL
A transaction in PL/SQL is a sequence of SQL statements that Oracle treats as a single unit of work. Transactions ensure data integrity using the principles of COMMIT and ROLLBACK.
- COMMIT: Saves all changes permanently.
- ROLLBACK: Cancels uncommitted changes.
- SAVEPOINT: Creates a checkpoint to roll back partially.
Example:
BEGIN
INSERT INTO students VALUES (101, 'Rahul', 'MCA');
INSERT INTO students VALUES (102, 'Ananya', 'BCA');
COMMIT;
END;
/
Example with ROLLBACK:
BEGIN
UPDATE students SET course='MBA' WHERE id=102;
ROLLBACK; -- Undo the change
END;
/
⚠️ Error Handling in PL/SQL
Errors in PL/SQL are called exceptions. These can be system-defined or user-defined.
1️⃣ System Defined Exceptions
Oracle automatically raises these for common runtime errors.
NO_DATA_FOUND– When SELECT returns no rowsZERO_DIVIDE– Division by zeroTOO_MANY_ROWS– SELECT returns more than one row
Example:
DECLARE
v_name students.name%TYPE;
BEGIN
SELECT name INTO v_name FROM students WHERE id=999;
DBMS_OUTPUT.PUT_LINE(v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No record found!');
END;
/
2️⃣ User Defined Exceptions
Developers can define custom exceptions for specific logic.
Example:
DECLARE
ex_invalid_id EXCEPTION;
v_id NUMBER := -5;
BEGIN
IF v_id < 0 THEN
RAISE ex_invalid_id;
END IF;
EXCEPTION
WHEN ex_invalid_id THEN
DBMS_OUTPUT.PUT_LINE('Invalid Student ID!');
END;
/
🎯 Cursors in PL/SQL
A cursor is a pointer that allows row-by-row processing of query results. When SQL statements return multiple rows, cursors help process them one at a time.
Types of Cursors
- Implicit Cursor: Automatically created by Oracle for SQL statements like SELECT INTO, INSERT, UPDATE, DELETE.
- Explicit Cursor: Defined by the programmer for queries returning multiple rows.
🔹 Implicit Cursor Example
BEGIN
UPDATE students SET course='MCA' WHERE id=101;
IF SQL%ROWCOUNT > 0 THEN
DBMS_OUTPUT.PUT_LINE('Record Updated');
END IF;
END;
/
🔹 Explicit Cursor Example
DECLARE
CURSOR c_student IS SELECT id, name FROM students;
v_id students.id%TYPE;
v_name students.name%TYPE;
BEGIN
OPEN c_student;
LOOP
FETCH c_student INTO v_id, v_name;
EXIT WHEN c_student%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_id || ' - ' || v_name);
END LOOP;
CLOSE c_student;
END;
/
✅ The cursor retrieves all student records one by one.
🔁 Cursor with FOR Loop
A FOR loop automatically opens, fetches, and closes the cursor — making code simpler.
BEGIN
FOR rec IN (SELECT id, name FROM students) LOOP
DBMS_OUTPUT.PUT_LINE(rec.id || ' : ' || rec.name);
END LOOP;
END;
/
📨 Parameterized Cursor
Parameterized cursors allow passing values at runtime, making them more flexible.
Example:
DECLARE
CURSOR c_course(c_name VARCHAR2) IS
SELECT id, name FROM students WHERE course = c_name;
BEGIN
FOR rec IN c_course('MCA') LOOP
DBMS_OUTPUT.PUT_LINE(rec.id || ' - ' || rec.name);
END LOOP;
END;
/
✅ Displays all students enrolled in MCA.
🧩 Nested Cursor
A nested cursor is one cursor inside another — often used when one query depends on another.
Example:
DECLARE
CURSOR c_dept IS SELECT dept_id, dept_name FROM department;
CURSOR c_emp(d_id NUMBER) IS SELECT emp_name FROM employee WHERE dept_id = d_id;
BEGIN
FOR d IN c_dept LOOP
DBMS_OUTPUT.PUT_LINE('Department: ' || d.dept_name);
FOR e IN c_emp(d.dept_id) LOOP
DBMS_OUTPUT.PUT_LINE(' Employee: ' || e.emp_name);
END LOOP;
END LOOP;
END;
/
✅ The inner cursor retrieves employees for each department from the outer cursor.
💡 Key Points Summary
- PL/SQL adds procedural capabilities to SQL.
- A PL/SQL block consists of DECLARE, BEGIN, EXCEPTION, and END sections.
- Transactions ensure data consistency with COMMIT and ROLLBACK.
- Exceptions (system and user-defined) handle runtime errors gracefully.
- Cursors enable row-by-row processing of query results.
- Parameterized and nested cursors enhance flexibility and performance.
🧠 Practice Exercise
Write a PL/SQL program to display all employees of a given department using a parameterized cursor. Add exception handling for invalid department IDs.
Written by Saksham Shekher — MCA student and web developer, sharing simple and practical explanations for core computer science topics.
