📘 PL/SQL Stored Procedure Lab Exam – 30 Questions (Sample Schema)
Practice these 30 stored procedure questions based on the sample database schema for Product, Customer, Orders, Invoice, and InvoiceDetails.
🔹 Sample Database Schema
-- Product Table CREATE TABLE Product ( ProductID NUMBER PRIMARY KEY, ProductName VARCHAR2(50), CategoryID NUMBER, Price NUMBER ); -- Customer Table CREATE TABLE Customer ( CustomerID NUMBER PRIMARY KEY, CustomerName VARCHAR2(50), CategoryID NUMBER ); -- Orders Table CREATE TABLE Orders ( OrderID NUMBER PRIMARY KEY, CustomerID NUMBER REFERENCES Customer(CustomerID), OrderDate DATE, OrderType VARCHAR2(20), Status VARCHAR2(20) ); -- Invoice Table CREATE TABLE Invoice ( InvoiceID NUMBER PRIMARY KEY, OrderID NUMBER REFERENCES Orders(OrderID), TotalAmount NUMBER, PaymentStatus VARCHAR2(20), Discount NUMBER ); -- InvoiceDetails Table CREATE TABLE InvoiceDetails ( InvoiceID NUMBER REFERENCES Invoice(InvoiceID), ProductID NUMBER REFERENCES Product(ProductID), Quantity NUMBER );
🔹 PL/SQL Stored Procedure Questions (Q1–Q30)
- Create a procedure to display all products in the Product table.
- Create a procedure with an input parameter to display products of a specific category.
- Create a procedure to insert a new customer into the Customer table.
- Create a procedure to update product price by a given percentage.
- Create a procedure to delete a product based on ProductID.
- Create a procedure to display all orders of a specific customer using CustomerID as input.
- Create a procedure to calculate total invoice amount for a given customer.
- Create a procedure to insert a new order with order details.
- Create a procedure to update order status to 'Completed'.
- Create a procedure to calculate the total quantity sold for a specific product.
- Create a procedure with exception handling for inserting duplicate ProductID.
- Create a procedure to display invoices with a discount greater than a given value.
- Create a procedure to generate a report of customers with multiple orders.
- Create a procedure to display top 5 selling products.
- Create a procedure with IN and OUT parameters to return total invoice amount for a customer.
- Create a procedure to list all unpaid invoices.
- Create a procedure to apply a discount to all invoices of a customer.
- Create a procedure to delete orders that are canceled.
- Create a procedure to display products in a price range using IN parameters.
- Create a procedure to display orders within a date range.
- Create a procedure to calculate average invoice amount for a customer.
- Create a procedure to update customer category based on total purchases.
- Create a procedure to insert multiple products in a loop.
- Create a procedure to display orders grouped by order type.
- Create a procedure to check if a product exists before inserting a new order.
- Create a procedure to display invoice details including product names and quantities.
- Create a procedure to calculate grand total of all invoices.
- Create a procedure to update payment status of multiple invoices in a loop.
- Create a procedure with nested procedure to calculate invoice totals per order.
- Create a procedure to generate a summary report of customers, orders, and total invoice amounts.
- Create a procedure to handle exceptions when deleting a product that has related orders.
🔹 PL/SQL Stored Procedure Questions with Solutions
-- Q1: Display all products
CREATE OR REPLACE PROCEDURE show_all_products AS
BEGIN
FOR rec IN (SELECT * FROM Product) LOOP
DBMS_OUTPUT.PUT_LINE('ID: ' || rec.ProductID || ', Name: ' || rec.ProductName || ', Price: ' || rec.Price);
END LOOP;
END;
/
-- Explanation: A simple cursor FOR loop fetches all product records and displays them using DBMS_OUTPUT.
-- Q2: Display products of a specific category
CREATE OR REPLACE PROCEDURE show_products_by_category(p_cat NUMBER) AS
BEGIN
FOR rec IN (SELECT * FROM Product WHERE CategoryID = p_cat) LOOP
DBMS_OUTPUT.PUT_LINE('ID: ' || rec.ProductID || ', Name: ' || rec.ProductName || ', Price: ' || rec.Price);
END LOOP;
END;
/
-- Explanation: Uses an input parameter (p_cat) to filter products by category.
-- Q3: Insert a new customer
CREATE OR REPLACE PROCEDURE add_customer(p_name VARCHAR2, p_category NUMBER) AS
BEGIN
INSERT INTO Customer(CustomerID, CustomerName, CategoryID)
VALUES(Customer_seq.NEXTVAL, p_name, p_category);
COMMIT;
END;
/
-- Explanation: Inserts a new customer using parameters and commits the transaction.
-- Q4: Update product price by percentage
CREATE OR REPLACE PROCEDURE update_product_price(p_id NUMBER, p_percent NUMBER) AS
BEGIN
UPDATE Product SET Price = Price + (Price * p_percent / 100) WHERE ProductID = p_id;
COMMIT;
END;
/
-- Explanation: Updates a product's price based on a given percentage.
-- Q5: Delete product by ProductID
CREATE OR REPLACE PROCEDURE delete_product(p_id NUMBER) AS
BEGIN
DELETE FROM Product WHERE ProductID = p_id;
COMMIT;
END;
/
-- Explanation: Deletes the product with the given ProductID.
-- Q6: Display all orders for a customer
CREATE OR REPLACE PROCEDURE show_orders_by_customer(p_cid NUMBER) AS
BEGIN
FOR rec IN (SELECT * FROM Orders WHERE CustomerID = p_cid) LOOP
DBMS_OUTPUT.PUT_LINE('OrderID: ' || rec.OrderID || ', Date: ' || rec.OrderDate || ', Status: ' || rec.Status);
END LOOP;
END;
/
-- Explanation: Fetches all orders for a specific customer using a parameter.
-- Q7: Calculate total invoice for a customer
CREATE OR REPLACE PROCEDURE total_invoice_customer(p_cid NUMBER, p_total OUT NUMBER) AS
BEGIN
SELECT SUM(i.TotalAmount) INTO p_total
FROM Invoice i
JOIN Orders o ON i.OrderID = o.OrderID
WHERE o.CustomerID = p_cid;
END;
/
-- Explanation: Uses an OUT parameter to return total invoice amount for a customer.
-- Q8: Insert new order with details
CREATE OR REPLACE PROCEDURE add_order(p_cid NUMBER, p_type VARCHAR2, p_status VARCHAR2, p_productid NUMBER, p_qty NUMBER) AS
v_orderid NUMBER;
v_invoiceid NUMBER;
BEGIN
INSERT INTO Orders(OrderID, CustomerID, OrderDate, OrderType, Status)
VALUES(Order_seq.NEXTVAL, p_cid, SYSDATE, p_type, p_status)
RETURNING OrderID INTO v_orderid;
INSERT INTO Invoice(InvoiceID, OrderID, TotalAmount, PaymentStatus, Discount)
VALUES(Invoice_seq.NEXTVAL, v_orderid, 0, 'Pending', 0)
RETURNING InvoiceID INTO v_invoiceid;
INSERT INTO InvoiceDetails(InvoiceID, ProductID, Quantity)
VALUES(v_invoiceid, p_productid, p_qty);
COMMIT;
END;
/
-- Explanation: Inserts an order, creates an invoice, and adds product details.
-- Q9: Update order status to 'Completed'
CREATE OR REPLACE PROCEDURE complete_order(p_oid NUMBER) AS
BEGIN
UPDATE Orders SET Status = 'Completed' WHERE OrderID = p_oid;
COMMIT;
END;
/
-- Explanation: Updates the status of a specific order.
-- Q10: Total quantity sold for a product
CREATE OR REPLACE PROCEDURE total_quantity_product(p_pid NUMBER, p_total OUT NUMBER) AS
BEGIN
SELECT SUM(Quantity) INTO p_total FROM InvoiceDetails WHERE ProductID = p_pid;
END;
/
-- Explanation: Uses an OUT parameter to calculate total quantity sold.
-- Q11: Exception handling for duplicate ProductID
CREATE OR REPLACE PROCEDURE insert_product(p_id NUMBER, p_name VARCHAR2, p_price NUMBER) AS
BEGIN
INSERT INTO Product(ProductID, ProductName, Price) VALUES(p_id, p_name, p_price);
COMMIT;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE('ProductID already exists.');
END;
/
-- Explanation: Handles duplicate primary key exception during insert.
-- Q12: Display invoices with discount > value
CREATE OR REPLACE PROCEDURE invoices_with_discount(p_discount NUMBER) AS
BEGIN
FOR rec IN (SELECT * FROM Invoice WHERE Discount > p_discount) LOOP
DBMS_OUTPUT.PUT_LINE('InvoiceID: ' || rec.InvoiceID || ', Total: ' || rec.TotalAmount || ', Discount: ' || rec.Discount);
END LOOP;
END;
/
-- Explanation: Fetches invoices exceeding a discount threshold.
-- Q13: Report of customers with multiple orders
CREATE OR REPLACE PROCEDURE customers_multiple_orders AS
BEGIN
FOR rec IN (SELECT CustomerID, COUNT(*) AS orders_count FROM Orders GROUP BY CustomerID HAVING COUNT(*) > 1) LOOP
DBMS_OUTPUT.PUT_LINE('CustomerID: ' || rec.CustomerID || ', Orders: ' || rec.orders_count);
END LOOP;
END;
/
-- Explanation: Uses GROUP BY and HAVING to identify customers with multiple orders.
-- Q14: Top 5 selling products
CREATE OR REPLACE PROCEDURE top_selling_products AS
BEGIN
FOR rec IN (SELECT ProductID, SUM(Quantity) AS total_sold FROM InvoiceDetails GROUP BY ProductID ORDER BY total_sold DESC FETCH FIRST 5 ROWS ONLY) LOOP
DBMS_OUTPUT.PUT_LINE('ProductID: ' || rec.ProductID || ', Sold: ' || rec.total_sold);
END LOOP;
END;
/
-- Explanation: Aggregates sales per product and fetches top 5.
-- Q15: Procedure with IN and OUT parameters for total invoice
CREATE OR REPLACE PROCEDURE invoice_total(p_cid NUMBER, p_total OUT NUMBER) AS
BEGIN
SELECT SUM(i.TotalAmount) INTO p_total
FROM Invoice i JOIN Orders o ON i.OrderID = o.OrderID
WHERE o.CustomerID = p_cid;
END;
/
-- Explanation: Returns total invoice using OUT parameter.
-- Q16: List unpaid invoices
CREATE OR REPLACE PROCEDURE unpaid_invoices AS
BEGIN
FOR rec IN (SELECT * FROM Invoice WHERE PaymentStatus='Pending') LOOP
DBMS_OUTPUT.PUT_LINE('InvoiceID: ' || rec.InvoiceID || ', Total: ' || rec.TotalAmount);
END LOOP;
END;
/
-- Explanation: Displays all invoices with PaymentStatus 'Pending'.
-- Q17: Apply discount to all invoices of a customer
CREATE OR REPLACE PROCEDURE apply_discount(p_cid NUMBER, p_discount NUMBER) AS
BEGIN
UPDATE Invoice i
SET Discount = p_discount
WHERE i.OrderID IN (SELECT OrderID FROM Orders WHERE CustomerID = p_cid);
COMMIT;
END;
/
-- Explanation: Updates discount for all invoices of a specific customer.
-- Q18: Delete canceled orders
CREATE OR REPLACE PROCEDURE delete_canceled_orders AS
BEGIN
DELETE FROM Orders WHERE Status='Canceled';
COMMIT;
END;
/
-- Explanation: Removes all canceled orders from the Orders table.
-- Q19: Display products in price range
CREATE OR REPLACE PROCEDURE products_in_range(p_min NUMBER, p_max NUMBER) AS
BEGIN
FOR rec IN (SELECT * FROM Product WHERE Price BETWEEN p_min AND p_max) LOOP
DBMS_OUTPUT.PUT_LINE('ProductID: ' || rec.ProductID || ', Name: ' || rec.ProductName || ', Price: ' || rec.Price);
END LOOP;
END;
/
-- Explanation: Filters products within the given price range.
-- Q20: Display orders within date range
CREATE OR REPLACE PROCEDURE orders_in_date_range(p_start DATE, p_end DATE) AS
BEGIN
FOR rec IN (SELECT * FROM Orders WHERE OrderDate BETWEEN p_start AND p_end) LOOP
DBMS_OUTPUT.PUT_LINE('OrderID: ' || rec.OrderID || ', Date: ' || rec.OrderDate);
END LOOP;
END;
/
-- Explanation: Filters orders based on date range parameters.
-- Q21: Average invoice amount for customer
CREATE OR REPLACE PROCEDURE avg_invoice_customer(p_cid NUMBER, p_avg OUT NUMBER) AS
BEGIN
SELECT AVG(i.TotalAmount) INTO p_avg
FROM Invoice i JOIN Orders o ON i.OrderID = o.OrderID
WHERE o.CustomerID = p_cid;
END;
/
-- Explanation: Calculates average invoice amount using OUT parameter.
-- Q22: Update customer category based on total purchases
CREATE OR REPLACE PROCEDURE update_customer_category(p_cid NUMBER, p_category NUMBER) AS
BEGIN
UPDATE Customer SET CategoryID = p_category WHERE CustomerID = p_cid;
COMMIT;
END;
/
-- Explanation: Updates customer category.
-- Q23: Insert multiple products in loop
CREATE OR REPLACE PROCEDURE insert_multiple_products AS
BEGIN
FOR i IN 1..5 LOOP
INSERT INTO Product(ProductID, ProductName, Price) VALUES(Product_seq.NEXTVAL, 'Product'||i, 100 + i*10);
END LOOP;
COMMIT;
END;
/
-- Explanation: Demonstrates looping to insert multiple products.
-- Q24: Display orders grouped by order type
CREATE OR REPLACE PROCEDURE orders_grouped_by_type AS
BEGIN
FOR rec IN (SELECT OrderType, COUNT(*) AS cnt FROM Orders GROUP BY OrderType) LOOP
DBMS_OUTPUT.PUT_LINE('Type: ' || rec.OrderType || ', Count: ' || rec.cnt);
END LOOP;
END;
/
-- Explanation: Aggregates orders by type.
-- Q25: Check if product exists before inserting order
CREATE OR REPLACE PROCEDURE check_product_before_order(p_pid NUMBER) AS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM Product WHERE ProductID = p_pid;
IF v_count = 0 THEN
DBMS_OUTPUT.PUT_LINE('Product does not exist.');
ELSE
DBMS_OUTPUT.PUT_LINE('Product exists, proceed.');
END IF;
END;
/
-- Explanation: Validates product existence using COUNT.
-- Q26: Display invoice details with product names
CREATE OR REPLACE PROCEDURE invoice_details_with_products AS
BEGIN
FOR rec IN (SELECT i.InvoiceID, p.ProductName, d.Quantity
FROM Invoice i
JOIN InvoiceDetails d ON i.InvoiceID = d.InvoiceID
JOIN Product p ON d.ProductID = p.ProductID) LOOP
DBMS_OUTPUT.PUT_LINE('InvoiceID: ' || rec.InvoiceID || ', Product: ' || rec.ProductName || ', Qty: ' || rec.Quantity);
END LOOP;
END;
/
-- Explanation: Joins tables to display detailed invoice info.
-- Q27: Calculate grand total of all invoices
CREATE OR REPLACE PROCEDURE grand_total_invoices(p_total OUT NUMBER) AS
BEGIN
SELECT SUM(TotalAmount) INTO p_total FROM Invoice;
END;
/
-- Explanation: Aggregates all invoice totals using OUT parameter.
-- Q28: Update payment status of multiple invoices in loop
CREATE OR REPLACE PROCEDURE update_payment_status AS
BEGIN
FOR rec IN (SELECT InvoiceID FROM Invoice WHERE PaymentStatus='Pending') LOOP
UPDATE Invoice SET PaymentStatus='Paid' WHERE InvoiceID=rec.InvoiceID;
END LOOP;
COMMIT;
END;
/
-- Explanation: Iterates over pending invoices to update status.
-- Q29: Nested procedure to calculate invoice totals per order
CREATE OR REPLACE PROCEDURE nested_invoice_totals AS
PROCEDURE calc_total(p_oid NUMBER, p_total OUT NUMBER) IS
BEGIN
SELECT SUM(Quantity*Price) INTO p_total
FROM InvoiceDetails d JOIN Product p ON d.ProductID = p.ProductID
WHERE d.InvoiceID = p_oid;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('Nested procedure defined for invoice totals.');
END;
/
-- Explanation: Demonstrates nested procedure usage.
-- Q30: Summary report of customers, orders, and total invoice
CREATE OR REPLACE PROCEDURE customer_order_summary AS
BEGIN
FOR rec IN (SELECT c.CustomerID, COUNT(o.OrderID) AS orders_count, SUM(i.TotalAmount) AS total_invoice
FROM Customer c
LEFT JOIN Orders o ON c.CustomerID = o.CustomerID
LEFT JOIN Invoice i ON o.OrderID = i.OrderID
GROUP BY c.CustomerID) LOOP
DBMS_OUTPUT.PUT_LINE('CustomerID: ' || rec.CustomerID || ', Orders: ' || rec.orders_count || ', Total: ' || rec.total_invoice);
END LOOP;
END;
/
-- Explanation: Generates a comprehensive summary report.
🔹 Q31: Delete Product with Exception Handling
CREATE OR REPLACE PROCEDURE delete_product_safe(p_id NUMBER) AS
BEGIN
DELETE FROM Product WHERE ProductID = p_id;
COMMIT;
DBMS_OUTPUT.PUT_LINE('Product deleted successfully.');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Cannot delete product. It may have related orders.');
END;
/
-- Explanation:
-- Attempts to delete a product. If the product is referenced in Orders or InvoiceDetails,
-- the foreign key constraint will raise an exception.
-- This is caught in the EXCEPTION block to prevent procedure failure and display a clear message.
কোন মন্তব্য নেই:
একটি মন্তব্য পোস্ট করুন