Adesso siamo un po' come agenti segreti — le nostre funzioni e procedure svolgono missioni: elaborano dati, fanno calcoli o semplicemente fanno magia dentro il database. Ma come facciamo a capire se qualcosa va storto? Come capire in che punto si è rotta la "vasca idromassaggio per i dati"? Qui ci vengono in aiuto logging e gestione degli errori.
Ricordi che abbiamo già iniziato a vedere come in PostgreSQL e PL/pgSQL si può "parlare" e scrivere log:
RAISE NOTICE: tono tranquillo, amichevole — "Ehi, qui va tutto bene, ma magari vuoi dare un'occhiata".RAISE WARNING: tono un po' più forte — "Ops, qui c'è qualcosa di strano, magari controlla".RAISE EXCEPTION: sirena di panico — "FERMO! L'algoritmo è nei guai! Abbiamo fermato tutto per evitare disastri".
Ognuno di questi livelli ha il suo scopo, ed è importante scegliere quello giusto da usare.
Ecco come appaiono questi messaggi nel codice:
DO $$
BEGIN
-- Livello NOTICE (tutto ok, solo una notifica)
RAISE NOTICE 'Solo una notifica: è iniziata l\'elaborazione dei dati';
-- Livello WARNING (qualcosa di sospetto)
RAISE WARNING 'Avviso: il formato dei dati nella colonna potrebbe essere non corretto';
-- Livello EXCEPTION (errore critico)
RAISE EXCEPTION 'Errore: valore di input non valido!';
END $$;
Quando usare:
RAISE NOTICE— per il debug e per mostrare info tranquille.RAISE WARNING— per avvisare di dati potenzialmente sbagliati.RAISE EXCEPTION— quando succedono errori critici che devono fermare l'esecuzione della funzione.
Gestione degli errori con RAISE EXCEPTION
RAISE EXCEPTION — è il tuo freno d'emergenza. Se qualcosa va storto, puoi fermare l'esecuzione della funzione e segnalare l'errore.
Ricordiamo, l'uso base è così:
RAISE EXCEPTION 'Il tuo messaggio di errore';
Ma per rendere i messaggi più informativi, puoi usare variabili:
DECLARE
input_value INTEGER;
BEGIN
input_value := NULL;
IF input_value IS NULL THEN
RAISE EXCEPTION 'Errore: valore di input NULL. Atteso valore INTEGER';
END IF;
END;
Formattazione dei messaggi
Puoi inserire variabili direttamente nel testo del messaggio:
DECLARE
var1 TEXT := 'Dati';
var2 INTEGER := 42;
BEGIN
RAISE EXCEPTION 'Errore durante l\'elaborazione di % con ID %', var1, var2;
END;
Output: Errore durante l'elaborazione di Dati con ID 42.
Esempio: validazione dei dati
Immagina di avere una procedura che prende l'età di una persona. Se l'età è negativa, ha senso lanciare un errore:
CREATE OR REPLACE FUNCTION validate_age(age INTEGER)
RETURNS VOID AS $$
BEGIN
IF age < 0 THEN
RAISE EXCEPTION 'L\'età non può essere negativa: %', age;
END IF;
END;
$$ LANGUAGE plpgsql;
-- Chiamata della funzione
SELECT validate_age(-5); -- Lancerà un errore
Informare con RAISE NOTICE
Se RAISE EXCEPTION è la sirena, RAISE NOTICE è una pacca amichevole sulla spalla. Con questo livello puoi aggiungere commenti per capire cosa succede dentro la funzione.
Quando usare RAISE NOTICE:
- Per mostrare info di debug (tipo lo stato attuale delle variabili).
- Per segnalare l'inizio di una fase o il risultato di un calcolo.
Esempio: messaggi informativi
CREATE OR REPLACE FUNCTION calculate_discount(price NUMERIC, discount_rate NUMERIC)
RETURNS NUMERIC AS $$
DECLARE
final_price NUMERIC;
BEGIN
RAISE NOTICE 'Prezzo prima dello sconto: %', price;
RAISE NOTICE 'Tasso di sconto: %', discount_rate;
final_price := price - (price * discount_rate);
RAISE NOTICE 'Prezzo finale: %', final_price;
RETURN final_price;
END;
$$ LANGUAGE plpgsql;
-- Chiamata della funzione
SELECT calculate_discount(100, 0.2);
-- Output:
-- NOTICE: Prezzo prima dello sconto: 100
-- NOTICE: Tasso di sconto: 0.2
-- NOTICE: Prezzo finale: 80
Applicazione pratica: pianificazione e logging
Supponiamo di avere una procedura complessa di elaborazione dati e vuoi sapere a che punto si trova:
CREATE OR REPLACE FUNCTION process_data_step_by_step()
RETURNS VOID AS $$
BEGIN
RAISE NOTICE 'Fase 1: Preparazione dei dati';
-- La tua logica per la prima fase
RAISE NOTICE 'Fase 2: Validazione dei dati';
-- La tua logica per la seconda fase
RAISE NOTICE 'Fase 3: Salvataggio dei dati';
-- La tua logica per la terza fase
END;
$$ LANGUAGE plpgsql;
-- Chiamata della funzione
SELECT process_data_step_by_step();
-- Nei log vedrai l'esecuzione passo passo
Facciamo un altro esempio. Immagina un negozio che offre sconti solo per ordini sopra una certa cifra:
CREATE OR REPLACE FUNCTION apply_discount(order_amount NUMERIC)
RETURNS NUMERIC AS $$
BEGIN
IF order_amount < 50 THEN
RAISE EXCEPTION 'Errore: l\'importo dell\'ordine deve essere almeno 50, importo attuale: %', order_amount;
END IF;
RETURN order_amount * 0.9; -- Applichiamo uno sconto del 10%
END;
$$ LANGUAGE plpgsql;
-- Chiamata della funzione
SELECT apply_discount(30); -- Errore: l'importo dell'ordine deve essere almeno 50
Errori tipici
Errore 1: loggare messaggi senza parametri.
Risulta poco informativo, soprattutto in procedure grandi:
RAISE NOTICE 'Si è verificato un errore'; -- Perché? Dove? Come?
Raccomandazione: aggiungi sempre il contesto:
RAISE NOTICE 'Errore nella funzione process_data(): valore di input: %', input_value;
Errore 2: usare RAISE EXCEPTION dove basta RAISE WARNING.
Se esageri con le eccezioni, il codice si fermerà per ogni cosa e diventa difficile gestire i dati.
Consiglio: usa i livelli di logging con consapevolezza. Per il debug scegli NOTICE, per i momenti critici — EXCEPTION.
Errore 3: niente logging.
È come cercare le chiavi al buio. Senza log, il debug di processi complessi è quasi impossibile.
Consiglio: aggiungi RAISE NOTICE nei punti chiave della funzione, soprattutto se è grande e complessa.
GO TO FULL VERSION