Home Database Introduction to PL/SQL — Oracle's Procedural SQL Extension

Introduction to PL/SQL — Oracle's Procedural SQL Extension

⚡ Quick Answer
SQL is like giving orders at a counter: 'Give me all customers from London.' One instruction, one response. PL/SQL is like handing the counter a recipe card: 'Look up customers from London, if there are more than 100 send a report, otherwise send a reminder — and repeat this every Monday.' PL/SQL gives SQL the ability to make decisions, loop, and remember state.

SQL is declarative — you describe what data you want and the database figures out how to get it. But real-world database logic often requires conditional branching, loops, error handling, and reusable procedures. That's what PL/SQL adds.

PL/SQL (Procedural Language extension to SQL) is Oracle's procedural extension to SQL. It runs inside the Oracle database engine itself, which means it avoids the round-trip overhead of sending individual SQL statements from an application. A loop that issues 1000 SQL statements from Java sends 1000 network requests. The same loop in PL/SQL sends one.

By the end of this article you'll understand the PL/SQL block structure, how to use variables, write conditionals and loops, and handle exceptions — the four pillars of every PL/SQL program.

The PL/SQL Block Structure

Every PL/SQL program is a block. Blocks have four sections: DECLARE (optional, for variables), BEGIN (required, the logic), EXCEPTION (optional, error handling), and END. Blocks can be anonymous (run once, not stored) or named (procedures and functions stored in the database). Understanding this structure is the foundation of everything else in PL/SQL.

first_block.sql · SQL
12345678910111213141516171819202122232425
-- Anonymous PL/SQL block — runs immediately, not stored
DECLARE
    -- Variable declarations
    v_employee_name  VARCHAR2(50);   -- String up to 50 chars
    v_salary         NUMBER(10, 2);  -- Number with 2 decimal places
    v_department_id  NUMBER := 10;   -- Initialised to 10

BEGIN
    -- Query into variables using SELECT INTO
    SELECT first_name || ' ' || last_name, salary
    INTO   v_employee_name, v_salary
    FROM   employees
    WHERE  department_id = v_department_id
    AND    ROWNUM = 1;

    -- Output using DBMS_OUTPUT (enable with SET SERVEROUTPUT ON)
    DBMS_OUTPUT.PUT_LINE('Employee: ' || v_employee_name);
    DBMS_OUTPUT.PUT_LINE('Salary: $' || TO_CHAR(v_salary, '999,999.99'));

EXCEPTION
    -- Handle the case where no rows are found
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('No employee found in department ' || v_department_id);
END;
/  -- The slash executes the block in SQL*Plus and SQLDeveloper
▶ Output
Employee: Steven King
Salary: $24,000.00
🔥
SET SERVEROUTPUT ON:Before running any PL/SQL that uses DBMS_OUTPUT.PUT_LINE, run SET SERVEROUTPUT ON in your session. Without it, output is silently discarded and you'll think nothing happened.

Variables, Conditions, and Loops

PL/SQL variables are strongly typed. The %TYPE attribute lets you declare a variable that automatically matches a table column's data type — if the column type changes, your variable adapts automatically. Conditionals use IF/ELSIF/ELSE. Loops come in three flavours: basic LOOP, WHILE, and the most common FOR loop.

loops_and_conditions.sql · SQL
123456789101112131415161718192021222324252627282930
DECLARE
    -- %TYPE anchors variable type to the actual column definition
    v_salary    employees.salary%TYPE;
    v_grade     VARCHAR2(10);
    v_counter   NUMBER;

BEGIN
    SELECT salary INTO v_salary
    FROM employees WHERE employee_id = 100;

    -- IF / ELSIF / ELSE
    IF v_salary > 20000 THEN
        v_grade := 'Executive';
    ELSIF v_salary > 10000 THEN
        v_grade := 'Senior';
    ELSIF v_salary > 5000 THEN
        v_grade := 'Mid-level';
    ELSE
        v_grade := 'Junior';
    END IF;

    DBMS_OUTPUT.PUT_LINE('Grade: ' || v_grade);

    -- FOR loop (most common) — implicit counter, no DECLARE needed
    FOR v_counter IN 1..5 LOOP
        DBMS_OUTPUT.PUT_LINE('Iteration: ' || v_counter);
    END LOOP;

END;
/
▶ Output
Grade: Executive
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4
Iteration: 5
⚠️
Use %TYPE and %ROWTYPE:Always use employees.salary%TYPE instead of hardcoding NUMBER(8,2). If the column definition changes, your code stays correct automatically. %ROWTYPE declares a variable matching an entire row structure.
FeatureSQLPL/SQL
TypeDeclarativeProcedural
ExecutionOne statement at a timeBlocks of logic
ConditionalsCASE (limited)IF/ELSIF/ELSE, CASE
LoopsNot supportedFOR, WHILE, LOOP
Error handlingNoneEXCEPTION block
ReusabilityViewsProcedures, functions, packages

🎯 Key Takeaways

  • PL/SQL extends SQL with variables, conditionals, loops, and exception handling
  • Every PL/SQL program is a block: DECLARE / BEGIN / EXCEPTION / END
  • %TYPE anchors variable types to table column definitions — use it always
  • PL/SQL runs inside the database engine — eliminates application-to-database round trips

⚠ Common Mistakes to Avoid

  • Mistake 1: Forgetting SET SERVEROUTPUT ON — DBMS_OUTPUT.PUT_LINE silently discards output if this is not set. Always run it at the start of your session.
  • Mistake 2: Using SELECT INTO when the query can return multiple rows — this raises TOO_MANY_ROWS exception. Use a cursor or aggregate function (MAX, MIN) when multiple rows are possible.
  • Mistake 3: Not ending the block with a forward slash (/) in SQL*Plus — without the slash the block is not submitted for execution. Nothing happens and no error appears.

Interview Questions on This Topic

  • QWhat are the four sections of a PL/SQL block and which are optional?
  • QWhat is the difference between %TYPE and %ROWTYPE?
  • QWhen would you use a PL/SQL procedure vs a function?
🔥
Naren Founder & Author

Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.

← PreviousPolyglot PersistenceNext →PL/SQL Variables, Constants and Data Types
Forged with 🔥 at TheCodeForge.io — Where Developers Are Forged