CodeGym /Kursy /SQL SELF /Analiza typowych błędów przy pracy z konstrukcjami steruj...

Analiza typowych błędów przy pracy z konstrukcjami sterującymi i logowaniem

SQL SELF
Poziom 52, Lekcja 4
Dostępny

Przechodząc do sedna, zatrzymajmy się na najczęstszych błędach i niedociągnięciach, na które możesz się natknąć. Bo błędy w SQL to ból każdego developera i zwykle pojawiają się w najmniej odpowiednim momencie.

1. Błędy składni: "zapomniałem zamknąć IF"

Błędy składni to najbardziej podstawowe problemy, ale pojawiają się częściej, niż myślisz. Na przykład, jeśli zapomnisz zamknąć blok warunkowy IF przez END IF;, kompilator od razu cię zgani.

Przykład błędu:

CREATE OR REPLACE FUNCTION check_number(num INTEGER)
RETURNS TEXT AS $$
BEGIN
    IF num > 0 THEN
        RETURN 'Pozytywna';
    ELSE
        RETURN 'Negatywna';
-- gdzieś zgubiło się END IF;
END;
$$ LANGUAGE plpgsql;

Przy próbie odpalenia tego kodu dostaniesz błąd: ERROR: syntax error at or near "END". Dlaczego? Bo blok IF został otwarty, ale nie zamknięty.

Jak unikać takich błędów?

Zawsze trzymaj się przejrzystej struktury kodu. Jak otwierasz blok (np. IF), od razu napisz jego zamknięcie. Oto poprawiony przykład:

CREATE OR REPLACE FUNCTION check_number(num INTEGER)
RETURNS TEXT AS $$
BEGIN
    IF num > 0 THEN
        RETURN 'Pozytywna';
    ELSE
        RETURN 'Negatywna';
    END IF; -- nie zapomnij zamknąć bloku
END;
$$ LANGUAGE plpgsql;

2. Zapomniana obsługa wszystkich przypadków w CASE: "A co, jeśli nie trafię nigdzie?"

Kiedy używasz CASE, zawsze dodaj gałąź ELSE na nieoczekiwane przypadki. Brak tej gałęzi może sprawić, że dostaniesz niechciane NULL.

Przykład błędu:

CREATE OR REPLACE FUNCTION grade_result(grade CHAR)
RETURNS TEXT AS $$
BEGIN
    RETURN CASE grade
        WHEN 'A' THEN 'Świetnie'
        WHEN 'B' THEN 'Dobrze'
        WHEN 'C' THEN 'Średnio'
        -- A co, jeśli grade = 'D' albo inna ocena?
    END;
END;
$$ LANGUAGE plpgsql;

Jeśli przekażesz wartość D, funkcja zwróci NULL, co może namieszać w twoim kodzie.

Poprawiona wersja:

CREATE OR REPLACE FUNCTION grade_result(grade CHAR)
RETURNS TEXT AS $$
BEGIN
    RETURN CASE grade
        WHEN 'A' THEN 'Świetnie'
        WHEN 'B' THEN 'Dobrze'
        WHEN 'C' THEN 'Średnio'
        ELSE 'Nieznana ocena' -- Łapiemy wszystkie inne przypadki
    END;
END;
$$ LANGUAGE plpgsql;

3. Problemy z nieskończonymi pętlami: "Czemu serwer się zawiesił?"

Używając pętli LOOP, łatwo zapomnieć o warunku wyjścia. To może skończyć się nieskończonym wykonaniem:

Przykład błędu:

CREATE OR REPLACE FUNCTION infinite_loop_demo()
RETURNS VOID AS $$
DECLARE
    i INTEGER := 1;
BEGIN
    LOOP
        i := i + 1;
        -- Brak warunku wyjścia!
    END LOOP;
END;
$$ LANGUAGE plpgsql;

Ten kod zawiesi serwer, bo pętla nigdy się nie skończy.

Jak naprawić:

Dodaj warunek wyjścia przez EXIT:

CREATE OR REPLACE FUNCTION finite_loop_demo()
RETURNS VOID AS $$
DECLARE
    i INTEGER := 1;
BEGIN
    LOOP
        i := i + 1;
        IF i > 10 THEN
            EXIT; -- Warunek wyjścia
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

4. Pomijanie iteracji w pętlach: "A co z brakującymi danymi?"

Używając CONTINUE do pomijania iteracji, możesz popełnić błąd, jeśli nie ogarniesz wszystkich przypadków. Na przykład:

Przykład błędu:

CREATE OR REPLACE FUNCTION skip_even()
RETURNS VOID AS $$
DECLARE
    i INTEGER := 0;
BEGIN
    WHILE i < 10 LOOP
        i := i + 1;
        IF i % 2 = 0 THEN
            CONTINUE; -- Po prostu pomijamy parzyste
        END IF;
        RAISE NOTICE 'Nieparzysta liczba: %', i;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

A co, jeśli wszystkie liczby będą parzyste? Serwer będzie działał, ale nic nie zobaczysz.

Jak naprawić:

Upewnij się, że dobrze obsługujesz wszystkie dane i dodaj logi dla kontroli:

CREATE OR REPLACE FUNCTION skip_even_logging()
RETURNS VOID AS $$
DECLARE
    i INTEGER := 0;
BEGIN
    WHILE i < 10 LOOP
        i := i + 1;
        IF i % 2 = 0 THEN
            RAISE NOTICE 'Pomijam parzystą: %', i;
            CONTINUE;
        END IF;
        RAISE NOTICE 'Nieparzysta liczba: %', i;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

Teraz widzisz, które liczby zostały pominięte.

5. Zła obsługa błędów: "Gdzie mój RAISE EXCEPTION?"

Obsługa błędów przez RAISE EXCEPTION to mocne narzędzie, ale łatwo je popsuć złym użyciem.

Przykład błędu:

CREATE OR REPLACE FUNCTION calculate_square(num INTEGER)
RETURNS INTEGER AS $$
BEGIN
    IF num < 0 THEN
        RAISE 'Liczba ujemna jest niedozwolona!';
    END IF;
    RETURN num * num;
END;
$$ LANGUAGE plpgsql;

Ten kod wywali błąd, bo składnia RAISE jest zła (brakuje poziomu komunikatu).

Poprawiona wersja:

CREATE OR REPLACE FUNCTION calculate_square(num INTEGER)
RETURNS INTEGER AS $$
BEGIN
    IF num < 0 THEN
        RAISE EXCEPTION 'Liczba ujemna jest niedozwolona!';
    END IF;
    RETURN num * num;
END;
$$ LANGUAGE plpgsql;

6. Błędy przy logowaniu: "Czemu moje błędy nie trafiają do error_log?"

Zła wstawka do tabeli error_log może się zdarzyć przez błędy w zapytaniach INSERT INTO.

Przykład błędu:

CREATE OR REPLACE FUNCTION log_error(err_msg TEXT)
RETURNS VOID AS $$
BEGIN
    INSERT INTO error_log (error_message, error_time)
    VALUES (err_msg, CURRENT_TIMESTAMP); -- A jeśli błąd w kolumnach?
END;
$$ LANGUAGE plpgsql;

Jeśli w tabeli error_log zmieniłeś nazwę kolumny (np. na error_msg), to wywali błąd.

Jak unikać:

Zawsze sprawdzaj strukturę tabeli albo używaj sztywnego schematu do zarządzania danymi.

7. Ogólna nieuwaga i "czynnik ludzki"

Błędy to nie tylko technika, ale też zwykła nieuwaga. Zapomniana diagnostyka, nieużywane zmienne czy brak formatowania mogą zamienić twoją funkcję w chaos.

Przykład:

DECLARE
    i INTEGER; -- Po co, skoro zmienna nie jest używana?

Poprawka: wywalaj niepotrzebne kawałki kodu, żeby był czysty i czytelny.

Teraz jesteś gotowy, żeby unikać najczęstszych błędów w PL/pgSQL i pisać kod, który daje więcej frajdy niż bólu. Nie zapominaj testować, logować i na bieżąco łatać bugi — zaoszczędzisz sobie masę nerwów i telefonów od klientów!

2
Zadanie
SQL SELF, poziom 52, lekcja 4
Niedostępne
Obsługa wszystkich warunków w `CASE`
Obsługa wszystkich warunków w `CASE`
1
Ankieta/quiz
Obsługa błędów, poziom 52, lekcja 4
Niedostępny
Obsługa błędów
Obsługa błędów
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION