Teraz jesteśmy trochę jak tajni agenci — nasze funkcje i procedury wykonują misje: przetwarzają dane, robią obliczenia albo po prostu czarują coś w bazie. Ale jak się dowiedzieć, jeśli coś pójdzie nie tak? Jak ogarnąć, na którym etapie rozwaliła się "masażowa wanienka dla danych"? Tu z pomocą przychodzą logowanie i obsługa błędów.
Pamiętasz, już zaczynaliśmy ogarniać, jak w PostgreSQL i PL/pgSQL można się "komunikować" i prowadzić logi:
RAISE NOTICE: spokojny, kumpelski ton — "Hej, wszystko gra, ale może chcesz na to zerknąć".RAISE WARNING: ton trochę głośniejszy — "Oj, coś tu dziwnego, może sprawdź".RAISE EXCEPTION: panika i syrena — "STOP! Algorytm w tarapatach! Zatrzymaliśmy wykonanie, żeby nie było katastrofy".
Każdy z tych poziomów ma swoje zastosowanie i ważne, żeby dobrze wybrać, którego użyć.
Tak wyglądają te wiadomości w kodzie:
DO $$
BEGIN
-- Poziom NOTICE (wszystko OK, tylko info)
RAISE NOTICE 'Po prostu info: zaczęło się przetwarzanie danych';
-- Poziom WARNING (coś podejrzanego)
RAISE WARNING 'Ostrzeżenie: format danych w kolumnie może być niepoprawny';
-- Poziom EXCEPTION (krytyczny błąd)
RAISE EXCEPTION 'Błąd: wartość wejściowa jest niedozwolona!';
END $$;
Kiedy używać:
RAISE NOTICE— do debugowania i spokojnego wypisywania informacji.RAISE WARNING— żeby ostrzec o potencjalnie złych danych.RAISE EXCEPTION— gdy dzieją się krytyczne błędy i trzeba zatrzymać funkcję.
Obsługa błędów z RAISE EXCEPTION
RAISE EXCEPTION — to twój hamulec bezpieczeństwa. Jeśli coś idzie nie tak, możesz zatrzymać wykonanie funkcji i zgłosić błąd.
Przypomnijmy, podstawowe użycie wygląda tak:
RAISE EXCEPTION 'Twoja wiadomość o błędzie';
Ale żeby wiadomości były bardziej konkretne, możesz użyć zmiennych:
DECLARE
input_value INTEGER;
BEGIN
input_value := NULL;
IF input_value IS NULL THEN
RAISE EXCEPTION 'Błąd: wartość wejściowa NULL. Oczekiwano wartości INTEGER';
END IF;
END;
Formatowanie wiadomości
Możesz wstawiać zmienne bezpośrednio do tekstu wiadomości:
DECLARE
var1 TEXT := 'Dane';
var2 INTEGER := 42;
BEGIN
RAISE EXCEPTION 'Błąd podczas przetwarzania % z ID %', var1, var2;
END;
Wynik: Błąd podczas przetwarzania Dane z ID 42.
Przykład: walidacja danych
Wyobraź sobie, że masz procedurę, która przyjmuje wiek człowieka. Jeśli wiek jest ujemny, logiczne jest rzucić błąd:
CREATE OR REPLACE FUNCTION validate_age(age INTEGER)
RETURNS VOID AS $$
BEGIN
IF age < 0 THEN
RAISE EXCEPTION 'Wiek nie może być ujemny: %', age;
END IF;
END;
$$ LANGUAGE plpgsql;
-- Wywołanie funkcji
SELECT validate_age(-5); -- Rzuci błąd
Informowanie z RAISE NOTICE
Jeśli RAISE EXCEPTION to syrena, to RAISE NOTICE to kumpelskie poklepanie po ramieniu. Dzięki temu poziomowi możesz wrzucać komentarze, żeby ogarnąć, co się dzieje w środku funkcji.
Kiedy używać RAISE NOTICE:
- Wypisywanie informacji do debugowania (np. aktualny stan zmiennych).
- Info o rozpoczęciu etapu albo wyniku obliczeń.
Przykład: wiadomości informacyjne
CREATE OR REPLACE FUNCTION calculate_discount(price NUMERIC, discount_rate NUMERIC)
RETURNS NUMERIC AS $$
DECLARE
final_price NUMERIC;
BEGIN
RAISE NOTICE 'Cena przed rabatem: %', price;
RAISE NOTICE 'Stawka rabatu: %', discount_rate;
final_price := price - (price * discount_rate);
RAISE NOTICE 'Cena końcowa: %', final_price;
RETURN final_price;
END;
$$ LANGUAGE plpgsql;
-- Wywołanie funkcji
SELECT calculate_discount(100, 0.2);
-- Wypisze:
-- NOTICE: Cena przed rabatem: 100
-- NOTICE: Stawka rabatu: 0.2
-- NOTICE: Cena końcowa: 80
Zastosowanie praktyczne: planowanie i logowanie
Załóżmy, że masz złożoną procedurę przetwarzania danych i chcesz wiedzieć, na którym etapie właśnie jest:
CREATE OR REPLACE FUNCTION process_data_step_by_step()
RETURNS VOID AS $$
BEGIN
RAISE NOTICE 'Krok 1: Przygotowanie danych';
-- Twoja logika dla pierwszego etapu
RAISE NOTICE 'Krok 2: Walidacja danych';
-- Twoja logika dla drugiego etapu
RAISE NOTICE 'Krok 3: Zapis danych';
-- Twoja logika dla trzeciego etapu
END;
$$ LANGUAGE plpgsql;
-- Wywołanie funkcji
SELECT process_data_step_by_step();
-- W logach pojawi się krok po kroku
Jeszcze jeden przykład. Wyobraźmy sobie sklep, który daje rabaty tylko dla zamówień powyżej określonej kwoty:
CREATE OR REPLACE FUNCTION apply_discount(order_amount NUMERIC)
RETURNS NUMERIC AS $$
BEGIN
IF order_amount < 50 THEN
RAISE EXCEPTION 'Błąd: kwota zamówienia musi być co najmniej 50, aktualna kwota: %', order_amount;
END IF;
RETURN order_amount * 0.9; -- Nakładamy 10% rabatu
END;
$$ LANGUAGE plpgsql;
-- Wywołanie funkcji
SELECT apply_discount(30); -- Błąd: kwota zamówienia musi być co najmniej 50
Typowe błędy
Błąd 1: logowanie wiadomości bez parametrów.
Wygląda mało informacyjnie, szczególnie w dużych procedurach:
RAISE NOTICE 'Wystąpił błąd'; -- Dlaczego? Gdzie? Jak?
Rekomendacja: zawsze dodawaj kontekst:
RAISE NOTICE 'Błąd w funkcji process_data(): wartość wejściowa: %', input_value;
Błąd 2: używanie RAISE EXCEPTION tam, gdzie wystarczy RAISE WARNING.
Jeśli przesadzisz z wyjątkami, kod będzie się przerywał z byle powodu, co utrudni przetwarzanie danych.
Wskazówka: używaj poziomów logowania świadomie. Do debugowania wybieraj NOTICE, a do krytycznych sytuacji — EXCEPTION.
Błąd 3: brak logowania w ogóle.
To jak szukanie kluczy w ciemnym pokoju. Bez logów debugowanie złożonych procesów jest prawie niemożliwe.
Wskazówka: dodawaj RAISE NOTICE na kluczowych etapach działania funkcji, szczególnie jeśli jest duża i skomplikowana.
GO TO FULL VERSION