CodeGym /Kursy /SQL SELF /Współpraca między funkcjami a procedurami

Współpraca między funkcjami a procedurami

SQL SELF
Poziom 55 , Lekcja 1
Dostępny

Parę poziomów temu już gadaliśmy o procedurach i funkcjach w PostgreSQL. Teraz czas wejść w temat głębiej.

Funkcje i procedury mogą działać osobno, ale najczęściej to właśnie ich współpraca decyduje o sukcesie całego systemu. Największy plus jest taki, że funkcje można wywoływać jedna z drugiej, przekazując dane i nawet odbierając wynik działania.

Funkcje vs Procedury: jaka jest różnica?

Przypomnijmy sobie, czym funkcje różnią się od procedur w PostgreSQL:

  • Funkcje (FUNCTION):

    • Zwracają wartości.
    • Można ich używać w SELECT.
    • Często służą do obliczeń albo przekształcania danych.
  • Procedury (PROCEDURE):

    • Nie zwracają wartości bezpośrednio.
    • Używane do operacji typu insert, update albo delete danych.
    • Wywołuje się je przez komendę CALL.

Przekazywanie danych między funkcjami

Przechodząc do praktyki, zaczniemy od prostego przykładu przekazywania danych między funkcją a procedurą. Generalnie, przekazywanie danych między funkcjami odbywa się przez parametry i zwracane wartości.

Tak wygląda wywołanie funkcji w środku innej funkcji:

CREATE OR REPLACE FUNCTION get_student_name(student_id INT)
RETURNS TEXT AS $$
DECLARE
    student_name TEXT;
BEGIN
    -- Pobieramy imię studenta po jego ID
    SELECT name INTO student_name FROM students WHERE id = student_id;

    -- Zwracamy imię
    RETURN student_name;
END;
$$ LANGUAGE plpgsql;

Tę funkcję można wywołać z innej funkcji:

CREATE OR REPLACE FUNCTION welcome_student(student_id INT)
RETURNS TEXT AS $$
DECLARE
    message TEXT;
BEGIN
    -- Pobieramy imię studenta przez inną funkcję
    message := 'Witaj, ' || get_student_name(student_id) || '!';

    -- Zwracamy powitanie
    RETURN message;
END;
$$ LANGUAGE plpgsql;
  1. Funkcja get_student_name zwraca imię studenta na podstawie jego identyfikatora (student_id).
  2. W drugiej funkcji — welcome_student — to imię jest używane do stworzenia powitania.

Uwaga: Pobieranie danych przez SELECT INTO zapisuje wynik zapytania do zmiennej PL/pgSQL.

Przykład wywołania procedur z funkcji

Teraz zobaczmy, jak wywołać procedurę z funkcji. Załóżmy, że mamy procedurę, która zapisuje czas wejścia studenta do systemu:

CREATE OR REPLACE PROCEDURE log_student_entry(student_id INT)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO log_entries(student_id, entry_time)
    VALUES (student_id, NOW());
END;
$$;

Teraz wywołamy tę procedurę z funkcji, gdzie będzie ona logować wejście i zwracać komunikat:

CREATE OR REPLACE FUNCTION student_login(student_id INT)
RETURNS TEXT AS $$
BEGIN
    -- Wywołujemy procedurę do logowania
    CALL log_student_entry(student_id);

    -- Zwracamy komunikat
    RETURN 'Logowanie studenta zapisane poprawnie.';
END;
$$ LANGUAGE plpgsql;

Praktyczne przykłady współpracy

Przykład 1: obliczanie sumy końcowej i logowanie zamówienia

Wyobraź sobie, że pracujesz z systemem zamówień online. Do obliczania sumy końcowej zamówienia masz funkcję:

CREATE OR REPLACE FUNCTION calculate_order_total(order_id INT)
RETURNS NUMERIC AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- Sumujemy wszystkie pozycje zamówienia
    SELECT SUM(price * quantity) INTO total
    FROM order_items
    WHERE order_id = order_id;

    RETURN total;
END;
$$ LANGUAGE plpgsql;

Do zapisania sumy końcowej zamówienia używasz procedury:

CREATE OR REPLACE PROCEDURE log_order_total(order_id INT, total NUMERIC)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO order_totals(order_id, total)
    VALUES (order_id, total);
END;
$$;

Teraz połączmy je razem:

CREATE OR REPLACE FUNCTION process_order(order_id INT)
RETURNS TEXT AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- Wywołujemy funkcję do obliczenia sumy końcowej
    total := calculate_order_total(order_id);

    -- Logujemy sumę końcową przez procedurę
    CALL log_order_total(order_id, total);

    RETURN 'Zamówienie przetworzone poprawnie.';
END;
$$ LANGUAGE plpgsql;

Przykład 2: pobieranie maksymalnego ratingu studenta i aktualizacja profilu

Funkcja do pobierania maksymalnego ratingu:

CREATE OR REPLACE FUNCTION get_highest_rating(student_id INT)
RETURNS INT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- Szukamy maksymalnego ratingu studenta
    SELECT MAX(rating) INTO max_rating
    FROM ratings
    WHERE student_id = student_id;

    RETURN max_rating;
END;
$$ LANGUAGE plpgsql;

Procedura do aktualizacji profilu studenta:

CREATE OR REPLACE PROCEDURE update_student_profile(student_id INT, max_rating INT)
LANGUAGE plpgsql
AS $$
BEGIN
    UPDATE students
    SET highest_rating = max_rating
    WHERE id = student_id;
END;
$$;

Funkcja do wywołania tych operacji:

CREATE OR REPLACE FUNCTION refresh_student_profile(student_id INT)
RETURNS TEXT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- Pobieramy maksymalny rating
    max_rating := get_highest_rating(student_id);

    -- Aktualizujemy profil studenta
    CALL update_student_profile(student_id, max_rating);

    RETURN 'Profil zaktualizowany poprawnie.';
END;
$$ LANGUAGE plpgsql;

Typowe błędy przy współpracy

Jeden z najczęstszych błędów — niezgodność typów danych między funkcją a procedurą. Na przykład, jeśli twoja procedura oczekuje parametru typu NUMERIC, a ty podasz INTEGER, PostgreSQL zgłosi błąd typu. Zawsze sprawdzaj, czy typy danych się zgadzają.

Kolejny błąd to cykliczne wywoływanie funkcji, gdy funkcja A wywołuje funkcję B, a ta znowu A. To prowadzi do nieskończonego wywoływania i zawieszenia systemu.

Praktyczne znaczenie

Po co nam taka współpraca? W realu funkcje i procedury działają jak "klocki" z których budujesz złożone systemy. Pozwalają podzielić kod na niezależne części, co ułatwia debugowanie, ponowne użycie i testowanie. Na przykład:

  • Na rozmowie kwalifikacyjnej mogą cię poprosić o napisanie funkcji, która wywołuje procedurę do wykonania złożonej operacji. Pokazanie praktycznych umiejętności współpracy to duży plus.
  • Przy tworzeniu prawdziwych aplikacji, takich jak sklepy internetowe, systemy logowania czy CRM, umiejętność sensownego organizowania funkcjonalności przez współpracę funkcji i procedur bardzo upraszcza kod.

Żeby jeszcze lepiej ogarnąć współpracę funkcji i procedur, możesz zajrzeć do oficjalnej dokumentacji PL/pgSQL.

2
Zadanie
SQL SELF, poziom 55, lekcja 1
Niedostępne
Aktualizacja profilu studenta na podstawie oceny
Aktualizacja profilu studenta na podstawie oceny
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION