SQL Practice Logo

SQLPractice Online

Oracle: Advanced PL/SQL: Concept

Module: Database-Specific Features

Advanced PL/SQL techniques transform slow programs into high-performance systems. Think of basic PL/SQL as driving a car in city traffic (stop-and-go, slow). Advanced PL/SQL is like driving on a highway (continuous flow, fast). The key difference: bulk operations eliminate context switches between PL/SQL and SQL engines. Instead of processing 10,000 rows one-by-one (10,000 context switches), bulk operations process all 10,000 in one operation (1 context switch). This matters because context switches are expensive - each one takes 1-2ms. For 10,000 rows: row-by-row = 10-20 seconds, bulk = 0.1 seconds (100x faster).

**1. FORALL - Bulk DML Operations**

FORALL executes DML (INSERT/UPDATE/DELETE) for entire array in single operation.

```sql

DECLARE

TYPE t_order_ids IS TABLE OF NUMBER INDEX BY PLS_INTEGER;

v_order_ids t_order_ids;

BEGIN

-- Load array

SELECT order_id BULK COLLECT INTO v_order_ids

FROM orders

WHERE status = 'PENDING'

FETCH FIRST 10000 ROWS ONLY;

-- Bulk update (10,000 rows in one operation)

FORALL i IN 1..v_order_ids.COUNT

UPDATE orders

SET status = 'PROCESSED', processed_at = SYSDATE

WHERE order_id = v_order_ids(i);

COMMIT;

DBMS_OUTPUT.PUT_LINE('Updated ' || SQL%ROWCOUNT || ' rows');

END;

/

-- Performance: 0.3 seconds (vs 30 seconds row-by-row, 100x faster)

```

**Why this matters**: Oracle ERP processes 1M+ records in batch jobs. Without FORALL, batch takes 8 hours. With FORALL, batch takes 5 minutes (96x faster).

**2. BULK COLLECT - Bulk SELECT Operations**

BULK COLLECT fetches multiple rows into array in single operation.

```sql

DECLARE

TYPE t_customers IS TABLE OF customers%ROWTYPE;

v_customers t_customers;

BEGIN

-- Fetch 10,000 rows in one operation

SELECT * BULK COLLECT INTO v_customers

FROM customers

WHERE status = 'ACTIVE'

FETCH FIRST 10000 ROWS ONLY;

-- Process array

FOR i IN 1..v_customers.COUNT LOOP

DBMS_OUTPUT.PUT_LINE('Customer: ' || v_customers(i).name);