RAISE și EXCEPTION (PL/pgSQL) în PostgreSQL

Funcții, proceduri și triggere PostgreSQL 8.0+ (RAISE ... USING: 8.4+)

RAISE afișează mesaje sau oprește codul cu o eroare; blocul EXCEPTION prinde erorile și le tratează.

Sintaxă SQL
RAISE [DEBUG | LOG | INFO | NOTICE | WARNING | EXCEPTION] 'mesaj cu %', valoare
    [USING HINT = '...', DETAIL = '...', ERRCODE = '...'];

BEGIN
    ...
EXCEPTION
    WHEN nume_eroare THEN ...
END;

Ce face RAISE și EXCEPTION (PL/pgSQL)

RAISE NOTICE trimite un mesaj informativ clientului, util la depanare. În textul mesajului, fiecare % este înlocuit cu următoarea valoare din listă. Nivelurile DEBUG și LOG nu se văd în psql cu setările implicite (client_min_messages = notice).

RAISE EXCEPTION oprește execuția și anulează tranzacția, ca orice eroare SQL. Cu USING poți adăuga HINT, DETAIL și un cod de eroare (ERRCODE), pe care aplicația îl poate verifica.

Un bloc BEGIN ... EXCEPTION WHEN ... THEN ... END prinde erorile din interiorul lui. Variabilele SQLERRM (mesajul) și SQLSTATE (codul) spun ce s-a întâmplat. Modificările din blocul care a eșuat sunt anulate automat.

Parametri

Parametru Descriere
NOTICE / WARNING Mesaje care nu opresc codul.
EXCEPTION Eroare: oprește codul (nivelul implicit dacă nu scrii nimic).
USING HINT / DETAIL / ERRCODE Informații suplimentare pentru eroare.
WHEN unique_violation / division_by_zero / OTHERS Ce erori prinde blocul EXCEPTION.

Ce returnează

Nimic; mesajele apar în psql ca NOTICE:, WARNING: sau ERROR:.

Exemple

Exemplul 1: Eroare cu indiciu pentru utilizator

Linia din CONTEXT se numără de la începutul corpului (prima linie este restul liniei cu DO $$).

DO $$
DECLARE
    stoc integer := 2;
BEGIN
    IF stoc < 5 THEN
        RAISE EXCEPTION 'Stoc insuficient: % bucăți', stoc
            USING HINT = 'Comandă mai puțin sau așteaptă reaprovizionarea.';
    END IF;
END
$$;

Rezultat în psql

ERROR:  Stoc insuficient: 2 bucăți
HINT:  Comandă mai puțin sau așteaptă reaprovizionarea.
CONTEXT:  PL/pgSQL function inline_code_block line 6 at RAISE

Exemplul 2: Prinderea unei erori de cheie duplicată

DO $$
BEGIN
    INSERT INTO clienti (email, nume) VALUES ('ana@exemplu.ro', 'Ana');
EXCEPTION
    WHEN unique_violation THEN
        RAISE NOTICE 'Clientul există deja (%): %', SQLSTATE, SQLERRM;
END
$$;

Rezultat în psql

NOTICE:  Clientul există deja (23505): duplicate key value violates unique constraint "clienti_email_key"
DO

Exemplul 3: Niveluri diferite de mesaje

DO $$
BEGIN
    RAISE DEBUG 'nu se vede cu setările implicite';
    RAISE INFO 'import pornit';
    RAISE WARNING '3 rânduri au codul poștal lipsă';
END
$$;

Rezultat în psql

INFO:  import pornit
WARNING:  3 rânduri au codul poștal lipsă
DO

Greșeli frecvente

  • Pui mai multe % decât valori (sau invers): PostgreSQL refuză blocul cu too few parameters specified for RAISE sau too many parameters specified for RAISE.
  • Prinzi toate erorile cu WHEN OTHERS THEN NULL: erorile reale dispar fără urmă. Prinde doar erorile pe care știi să le tratezi.
  • Folosești blocuri EXCEPTION într-o buclă cu milioane de pași: fiecare intrare în bloc creează un savepoint, ceea ce costă timp.

Comenzi înrudite

  • DO (bloc anonim): Rulează o singură dată un bloc de cod PL/pgSQL, fără să creeze o funcție. Util pentru scripturi de întreținere și migrări.
  • CREATE FUNCTION (LANGUAGE plpgsql): Creează o funcție în PL/pgSQL, limbajul procedural al PostgreSQL: variabile, IF, bucle, tratarea erorilor.
  • CREATE TRIGGER: Rulează automat o funcție la INSERT, UPDATE sau DELETE pe un tabel, de exemplu pentru a completa coloana actualizat_la sau pentru jurnal de audit.