CodeGym /Kursy /SQL SELF /Podstawy składni PL/pgSQL

Podstawy składni PL/pgSQL

SQL SELF
Poziom 49 , Lekcja 3
Dostępny

Wejdźmy głębiej w PL/pgSQL i zacznijmy korzystać z niego bardziej na serio.

Blok kodu

Blok kodu w PL/pgSQL to taki główny klocek budulcowy języka. Można powiedzieć, że to szkielet, na którym wiszą nasze funkcje, procedury i cała ta magia. Blok ogarnia wykonywanie logiki, przetwarzanie danych, obsługę błędów – wszystko w jednym "kontenerze".

Bloki PL/pgSQL są uporządkowane i mają trzy główne części:

  1. DECLARE: deklaracja zmiennych (opcjonalnie).
  2. BEGIN ... END: główny blok wykonania, gdzie dzieje się cała logika.
  3. EXCEPTION: obsługa błędów (opcjonalnie).

Dla fanów analogii: wyobraź sobie przepis na danie. Chociaż tekst przepisu może zaczynać się od listy składników, cała magia dzieje się podczas gotowania. W PL/pgSQL:

  • DECLARE — to lista składników (zmienne).
  • BEGIN ... END — tu się miesza, smaży i gotuje.
  • EXCEPTION — to plan awaryjny, jak coś się przypali.

Składnia bloku PL/pgSQL

Najpierw zobaczmy ogólną strukturę bloku, taki "szkielet". Potem dorzucimy mięso (albo wege ser, jak wolisz) – konkretną logikę.

DO $$
DECLARE
    -- Tutaj deklarujemy zmienne
    student_count INT;
BEGIN
    -- Tutaj wykonujemy logikę
    SELECT COUNT(*) INTO student_count FROM students;
    RAISE NOTICE 'Całkowita liczba studentów: %', student_count;
EXCEPTION
    -- Tutaj obsługujemy błędy
    WHEN OTHERS THEN
        RAISE NOTICE 'Wystąpił błąd.';
END;
$$;

Rozłóżmy to na części pierwsze.

  1. DECLARE — tutaj deklarujemy nasze zmienne. Fajne jest to, że PL/pgSQL obsługuje prawie wszystkie typy danych dostępne w PostgreSQL – od zwykłego INTEGER po egzotyczne JSONB. Żeby zadeklarować zmienną, podajesz jej nazwę, typ danych i, jeśli chcesz, wartość początkową.

Przykład:

DECLARE
    student_name TEXT;    -- Zmienna na imię studenta
    course_count INT := 0; -- Ustawiamy początkową wartość na 0
    is_graduated BOOLEAN; -- Zmienna logiczna

Zwróć uwagę, że zmienne mogą być z inicjalizacją (jak course_count) albo bez.

  1. BEGIN ... END — główny blok wykonania.

Ta część bloku odpowiada za całą logikę. Tutaj możesz:

  • Wykonywać zapytania SQL (SELECT, INSERT, itd.).
  • Manipulować danymi.
  • Używać konstrukcji sterujących (IF, LOOP, itd.).
  • Wyświetlać komunikaty debugowe przez RAISE.

Przykład:

BEGIN
    SELECT COUNT(*) INTO student_count FROM students;
    IF student_count > 0 THEN
        RAISE NOTICE 'Mamy studentów!';
    ELSE
        RAISE NOTICE 'Nie znaleziono studentów.';
    END IF;
END;
  1. EXCEPTION — obsługa błędów (opcjonalnie).

Jeśli podczas wykonywania bloku pojawi się błąd, sekcja EXCEPTION pozwala go przechwycić i zrobić coś sensownego – np. wyświetlić komunikat albo wykonać alternatywny kod.

Przykład:

BEGIN
    SELECT COUNT(*) INTO student_count FROM non_existing_table; -- Błąd!
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE 'Ups, coś poszło nie tak!';
END;

Prawdziwy przykład: liczenie studentów

Teraz złóżmy wszystko w całość na przykładzie, który może się przydać w realu. Napiszemy blok PL/pgSQL, który liczy liczbę studentów w tabeli students i wyświetla komunikat.

DO $$
DECLARE
    total_students INT; -- Zmienna do przechowywania liczby studentów
BEGIN
    -- Liczymy liczbę studentów
    SELECT COUNT(*) INTO total_students FROM students;

    -- Wyświetlamy komunikat z wynikiem
    RAISE NOTICE 'Liczba studentów: %', total_students;
EXCEPTION
    -- Obsługujemy możliwe błędy, np. jeśli tabela nie istnieje
    WHEN OTHERS THEN
        RAISE NOTICE 'Wystąpił błąd podczas liczenia studentów.';
END;
$$;

Wywołanie tego bloku wyświetli komunikat w konsoli. Na przykład: Liczba studentów: 42.

Szczegóły używania zmiennych

Ogarniemy kilka ważnych rzeczy:

Przypisywanie wartości do zmiennych. Żeby wrzucić dane do zmiennej, użyj operatora SELECT INTO:

SELECT COUNT(*) INTO total_students FROM students;

Inicjalizacja zmiennych. Jeśli nie przypiszesz wartości zmiennej przy deklaracji, jej wartość domyślna to NULL.

Na przykład:

DECLARE
    my_var INT; -- Wartość to NULL

Zmienne typu RECORD. To uniwersalny typ zmiennej, do której można wrzucać wiersze z tabeli. Przykład:

DECLARE
    student RECORD;
BEGIN
    SELECT * INTO student FROM students WHERE id = 1;
    RAISE NOTICE 'Imię studenta: %, Wiek: %', student.name, student.age;
END;

Przykład: liczenie kursów dla studenta

Teraz rozwiążemy praktyczny problem: policzymy, ile kursów ma zapisanych student i wyświetlimy wynik.

DO $$
DECLARE
    student_id INT := 1;   -- ID studenta
    course_count INT;      -- Zmienna na liczbę kursów
BEGIN
    -- Liczymy liczbę kursów
    SELECT COUNT(*) INTO course_count
    FROM enrollments
    WHERE student_id = student_id;

    -- Wyświetlamy komunikat
    RAISE NOTICE 'Student ID % jest zapisany na % kursów.', student_id, course_count;
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE 'Wystąpił błąd podczas przetwarzania studenta ID %', student_id;
END;
$$;

Ten blok jest elastyczny: możesz zmieniać student_id, żeby sprawdzić, ile kursów mają różni studenci.

Błędy i jak ich unikać

Jeśli PL/pgSQL w Tobie już się gotuje jak hot-dog w mikrofalówce, to normalne. Na początku łatwo trafić na "typowe" błędy. Oto kilka przykładów:

Brak deklaracji zmiennej. Jeśli zapomnisz zadeklarować zmienną przez DECLARE, PL/pgSQL wywali błąd, że zmienna "nie istnieje".

Próba użycia NULL jako wartości. Jeśli zmienna została zadeklarowana, ale nie dostała wartości, jej wartość to NULL. To może powodować dziwne zachowania. Na przykład:

IF my_var = NULL THEN -- NIE zadziała!

Użyj IS NULL:

IF my_var IS NULL THEN

Złe użycie sekcji EXCEPTION. Czasem programiści łapią wszystkie błędy (WHEN OTHERS), ale nie piszą, co zrobić. To może ukryć prawdziwy problem. Lepiej wypisać komunikat o błędzie:

RAISE NOTICE 'Błąd: %', SQLERRM;
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION