Skip to main content

What is PL/SQL Basics?

PL/SQL Basics refers to the fundamental building blocks of Oracle’s Procedural Language extension to SQL. Often called “PL/SQL Fundamentals” or “PL/SQL Core Concepts,” it provides the structural and syntactic foundation for writing procedural code that executes within the Oracle Database.
The core purpose is to overcome SQL’s limitation as a declarative language by adding procedural capabilities like variables, conditional logic, loops, and error handling.
This solves the problem of building complex, efficient database applications that require multiple SQL operations with business logic, while minimizing network round-trips between application and database layers.

PL/SQL Blocks

PL/SQL programs are structured as blocks - logical units that group declarations and statements. Blocks can be named (functions, procedures) or anonymous (inline execution).
-- Anonymous PL/SQL Block structure
DECLARE
  -- Variable declarations go here
BEGIN
  -- Executable statements go here
EXCEPTION
  -- Error handling goes here
END;
/

DECLARE Section

The DECLARE section is optional and contains definitions of variables, constants, cursors, and user-defined types that will be used in the block.
DECLARE
  -- Variable declaration with data type
  employee_id NUMBER(6) := 100;
  
  -- Constant declaration
  tax_rate CONSTANT NUMBER(4,2) := 0.15;
  
  -- Variable with default value
  employee_name VARCHAR2(50) DEFAULT 'John Doe';
  
  -- Record type variable
  TYPE emp_rec IS RECORD (
    id employees.employee_id%TYPE,
    name employees.last_name%TYPE
  );
  rec emp_rec;
BEGIN
  -- Executable code follows
  NULL;
END;
/

BEGIN Section

The BEGIN section contains the executable statements that form the main logic of the PL/SQL block.
The BEGIN section is where your business logic and SQL operations are executed.
DECLARE
  total_salary NUMBER := 0;
  emp_count NUMBER := 0;
BEGIN
  -- SQL operation within PL/SQL
  SELECT SUM(salary), COUNT(*) 
  INTO total_salary, emp_count
  FROM employees 
  WHERE department_id = 50;
  
  -- Procedural logic
  IF emp_count > 0 THEN
    -- Assignment statement
    total_salary := total_salary * 1.1; -- 10% bonus
  END IF;
  
  -- Output result
  DBMS_OUTPUT.PUT_LINE('Total adjusted salary: ' || total_salary);
END;
/

EXCEPTION Section

The EXCEPTION section handles runtime errors gracefully, preventing program termination.
Always include exception handling to make your PL/SQL code robust and production-ready.
DECLARE
  emp_salary employees.salary%TYPE;
  invalid_dept EXCEPTION;
  PRAGMA EXCEPTION_INIT(invalid_dept, -2291);
BEGIN
  -- This might raise an exception if department doesn't exist
  SELECT salary INTO emp_salary
  FROM employees 
  WHERE department_id = 999; -- Non-existent department
  
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE('No employees found in specified department');
  WHEN invalid_dept THEN
    DBMS_OUTPUT.PUT_LINE('Invalid department reference');
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Unexpected error: ' || SQLERRM);
END;
/

END Statement

The END statement marks the conclusion of the PL/SQL block and can include the block label for clarity.
<<salary_calculator>>
DECLARE
  -- declarations
BEGIN
  -- executable statements
EXCEPTION
  -- exception handlers
END salary_calculator;  -- Labeled END for readability
/

Variables and Constants

Variables store values that can change during execution, while constants hold immutable values.
Use %TYPE to anchor variables to table columns, ensuring type consistency.
DECLARE
  -- Variable (can be modified)
  counter NUMBER := 0;
  
  -- Constant (cannot be modified after declaration)
  company_name CONSTANT VARCHAR2(30) := 'Oracle Corporation';
  
  -- Variable using anchored datatype (%TYPE)
  emp_last_name employees.last_name%TYPE;
BEGIN
  counter := counter + 1;  -- Valid: variable modification
  -- company_name := 'New Name';  -- Invalid: constant cannot be modified
  
  -- Using anchored variable
  SELECT last_name INTO emp_last_name
  FROM employees WHERE employee_id = 100;
  
  DBMS_OUTPUT.PUT_LINE('Employee: ' || emp_last_name);
END;
/

Data Types

PL/SQL supports scalar, composite, reference, and LOB data types.
DECLARE
  -- Scalar types
  emp_id NUMBER(6);
  emp_name VARCHAR2(50);
  hire_date DATE := SYSDATE;
  is_active BOOLEAN := TRUE;
  
  -- Composite type (record)
  TYPE employee_record IS RECORD (
    id employees.employee_id%TYPE,
    name employees.last_name%TYPE,
    salary employees.salary%TYPE
  );
  emp_rec employee_record;
  
  -- Composite type (collection)
  TYPE name_array IS TABLE OF VARCHAR2(100) INDEX BY PLS_INTEGER;
  names name_array;
BEGIN
  -- Using scalar type
  emp_id := 101;
  emp_name := 'Smith';
  
  -- Using record type
  emp_rec.id := 102;
  emp_rec.name := 'Johnson';
  emp_rec.salary := 5000;
  
  -- Using collection
  names(1) := 'Alice';
  names(2) := 'Bob';
END;
/

Control Structures

Control structures manage program flow through conditionals and loops.
Control structures are essential for implementing complex business logic.
DECLARE
  score NUMBER := 85;
  i NUMBER;
  total NUMBER := 0;
BEGIN
  -- Conditional (IF-THEN-ELSIF)
  IF score >= 90 THEN
    DBMS_OUTPUT.PUT_LINE('Grade: A');
  ELSIF score >= 80 THEN
    DBMS_OUTPUT.PUT_LINE('Grade: B');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Grade: C or below');
  END IF;
  
  -- Loop (FOR)
  FOR i IN 1..5 LOOP
    total := total + i;
    DBMS_OUTPUT.PUT_LINE('Iteration: ' || i);
  END LOOP;
  
  -- Loop (WHILE)
  i := 1;
  WHILE i <= 3 LOOP
    DBMS_OUTPUT.PUT_LINE('While loop iteration: ' || i);
    i := i + 1;
  END LOOP;
  
  DBMS_OUTPUT.PUT_LINE('Total: ' || total);
END;
/

Why is PL/SQL Basics Important?

Procedural Abstraction

Structured Programming Principle: Encapsulates complex operations into manageable blocks, promoting maintainable code organization over unstructured spaghetti code.

DRY Principle

Don’t Repeat Yourself: Through variables, constants, and reusable blocks, PL/SQL eliminates code duplication by centralizing business logic within the database.

Separation of Concerns

SOLID Principle: Proper use of declaration, execution, and exception sections separates variable definition, business logic, and error handling into distinct responsibilities.

Advanced Nuances

Exception Propagation in Nested Blocks

Use nested blocks and exception propagation for sophisticated error handling strategies.
BEGIN
  <<outer_block>>
  DECLARE
    result NUMBER;
  BEGIN
    <<inner_block>>
    BEGIN
      -- This exception will propagate to outer_block
      SELECT 1/0 INTO result FROM dual;
    EXCEPTION
      WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Inner handled: ' || SQLERRM);
        RAISE;  -- Re-raise to outer block
    END inner_block;
  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('Outer handled: ' || SQLERRM);
  END outer_block;
END;
/

Dynamic SQL with EXECUTE IMMEDIATE

DECLARE
  table_not_exist EXCEPTION;
  PRAGMA EXCEPTION_INIT(table_not_exist, -942);
BEGIN
  -- Attempt to query non-existent table
  EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM non_existent_table';
EXCEPTION
  WHEN table_not_exist THEN
    -- Dynamic recovery: create table and retry
    EXECUTE IMMEDIATE 'CREATE TABLE non_existent_table (id NUMBER)';
    DBMS_OUTPUT.PUT_LINE('Table created dynamically');
END;
/

Bulk Operations with Control Structures

Use FORALL for bulk DML operations to improve performance dramatically.
DECLARE
  TYPE id_array IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
  TYPE name_array IS TABLE OF VARCHAR2(50) INDEX BY PLS_INTEGER;
  ids id_array;
  names name_array;
BEGIN
  -- Initialize collections
  FOR i IN 1..5 LOOP
    ids(i) := i * 100;
    names(i) := 'Employee_' || i;
  END LOOP;
  
  -- Bulk SQL operation using FORALL
  FORALL i IN 1..ids.COUNT
    INSERT INTO employees_temp (employee_id, last_name)
    VALUES (ids(i), names(i));
    
  DBMS_OUTPUT.PUT_LINE('Bulk inserted: ' || SQL%ROWCOUNT || ' rows');
END;
/

How This Fits the Roadmap

Within the “PL/SQL Programming” section, PL/SQL Basics serves as the foundational layer upon which all advanced topics are built.

Absolute Prerequisites For:

  • Stored Program Units (procedures, functions, packages)
  • Advanced Cursor Techniques
  • Collection Processing
  • Error Management Strategies
  • PL/SQL Compiler behavior understanding

Unlocks:

  • Entire spectrum of database programming capabilities
  • Sophisticated PL/SQL applications
  • Enterprise-scale development
  • Performance tuning opportunities

Build docs developers (and LLMs) love