Task 7:
7. Program development using WHILE LOOPS, numeric FOR LOOPS, nested loops
using ERROR Handling, BUILT –IN Exceptions, USE defined Exceptions, RAISE-
APPLICATION ERROR.
PL/SQL program demonstrating WHILE loops, numeric FOR loops, nested loops, error
handling, built-in exceptions, user-defined exceptions, and the use of
RAISE_APPLICATION_ERROR.
Scenario
The program processes a list of students and their marks. It:
1. Loops through a list of students using a FOR loop.
2. Calculates and prints a running total of marks using a WHILE loop.
3. Demonstrates nested loops to check for duplicate StudentID.
4. Implements error handling:
o Built-in exceptions: Handle division by zero.
o User-defined exceptions: Raise an error if a student's marks are invalid (e.g.,
negative or above 100).
o RAISE_APPLICATION_ERROR: Provide a meaningful error message.
Step 1: Create Table and Insert Data
Create the Students Table:
Sql>CREATE TABLE Students (
StudentID INT PRIMARY KEY,
Name VARCHAR(100) NOT NULL,
Marks INT CHECK (Marks BETWEEN 0 AND 100)
);
Insert Sample Data:
Sql>INSERT INTO Students VALUES (1, 'Alice', 85);
Sql>INSERT INTO Students VALUES (2, 'Bob', 72);
Sql>INSERT INTO Students VALUES (3, 'Charlie', 48);
Sql>INSERT INTO Students VALUES (4, 'Diana', 64);
Sql>INSERT INTO Students VALUES (5, 'Eve', 101);
Step 2: PL/SQL Program
DECLARE
-- Cursor to fetch students
CURSOR StudentCursor IS
SELECT StudentID, Name, Marks
FROM Students;
-- Variables for processing
v_StudentID Students.StudentID%TYPE;
v_Name Students.Name%TYPE;
v_Marks Students.Marks%TYPE;
v_TotalMarks INT := 0;
v_DuplicateCount INT; -- Variable to store count of duplicate IDs
-- User-defined exception
InvalidMarks EXCEPTION;
BEGIN
-- FOR loop to iterate through all students
FOR StudentRecord IN StudentCursor LOOP
v_StudentID := StudentRecord.StudentID;
v_Name := StudentRecord.Name;
v_Marks := StudentRecord.Marks;
-- Check for invalid marks and raise user-defined exception
IF v_Marks < 0 OR v_Marks > 100 THEN
RAISE InvalidMarks;
END IF;
DBMS_OUTPUT.PUT_LINE('Processing Student: ' || v_Name || ', Marks: ' || v_Marks);
-- Optimized total marks calculation
v_TotalMarks := v_TotalMarks + v_Marks;
-- FIX: Use SELECT INTO to check for duplicate IDs
SELECT COUNT(*) INTO v_DuplicateCount FROM Students WHERE StudentID =
v_StudentID;
IF v_DuplicateCount > 1 THEN
DBMS_OUTPUT.PUT_LINE('Duplicate StudentID found for: ' || v_Name);
END IF;
END LOOP;
-- Print total marks after processing all students
DBMS_OUTPUT.PUT_LINE('Total Marks Processed: ' || v_TotalMarks);
EXCEPTION
-- Handle user-defined exception
WHEN InvalidMarks THEN
DBMS_OUTPUT.PUT_LINE('Error: Invalid marks detected. Please check the data.');
-- Handle division by zero (example built-in exception)
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('Error: Division by zero occurred.');
-- Generic error handling using RAISE_APPLICATION_ERROR
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20001, 'An unexpected error occurred: ' ||
SQLERRM);
END;
/
Step 3: Explanation
1. FOR Loop:
o Iterates through all students using the StudentCursor.
o Prints student details and validates marks.
2. WHILE Loop:
o Used to calculate the total marks by iterating up to the value of Marks.
3. Nested Loops:
o Checks for duplicate StudentID within the table.
4. Error Handling:
o User-defined exception (InvalidMarks): Raised for marks outside the valid
range
(0–100).
o Built-in exception (ZERO_DIVIDE): Handled as an example but not triggered in
this case.
o Generic error handling: Uses RAISE_APPLICATION_ERROR for other
exceptions.
Step 4: Output
Case 1: Valid Data
If all marks are valid:
Processing Student: Alice, Marks: 85
Processing Student: Bob, Marks: 72
Processing Student: Charlie, Marks: 48
Processing Student: Diana, Marks: 64
Total Marks Processed: [Dynamic Value]
Case 2: Invalid Marks
If a student has invalid marks (e.g., Eve with 101):
Processing Student: Alice, Marks: 85
Processing Student: Bob, Marks: 72
Error: Invalid marks detected. Please check the data.
Step 5: Notes
Enable Output: Ensure that DBMS_OUTPUT is enabled:
Sql>SET SERVEROUTPUT ON;