CodeGym /Kursy /SQL SELF /Kontrola wykonywania funkcji: PERFORM

Kontrola wykonywania funkcji: PERFORM

SQL SELF
Poziom 55, Lekcja 3
Dostępny

PERFORM w świecie PostgreSQL to taki twardy, milczący bohater, który przychodzi, robi swoje i znika, nie zostawiając po sobie żadnych śladów w postaci zwracanych danych. Ta komenda jest używana, gdy chcesz wykonać zapytanie SQL wewnątrz funkcji PL/pgSQL, ale nie musisz przetwarzać ani zapisywać wyniku. Główne zadanie PERFORM to wywołać zapytanie, żeby coś się wydarzyło, na przykład modyfikacja danych albo wywołanie innej funkcji, a nie pobranie wyniku.

PERFORM używasz wtedy, gdy wynik zapytania nie jest ci potrzebny. W przeciwieństwie do zwykłego SELECT, który oczekuje, że coś z tym wynikiem zrobisz, PERFORM po prostu odpala zapytanie i idzie dalej. To mega wygodne, jeśli wywołujesz funkcję tylko dla jej efektu, a nie dla tego, co zwraca. Na przykład, żeby coś zapisać do loga. Takie podejście sprawia, że kod jest prostszy i bardziej czytelny: mniej zbędnych rzeczy, więcej sensu.

Przykłady użycia PERFORM

Wywoływanie funkcji

Ogarnijmy to na realnym przykładzie. Wyobraź sobie, że mamy funkcję log_action, która zapisuje info o działaniach użytkownika do logów. Ta funkcja nic nie zwraca i po prostu chcemy, żeby się wykonała. Tak to się robi z PERFORM:

CREATE OR REPLACE FUNCTION log_action(user_id INT, action TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO logs (user_id, action, log_time)
    VALUES (user_id, action, NOW());
END;
$$ LANGUAGE plpgsql;

-- Dalej używamy PERFORM do wywołania tej funkcji:
PERFORM log_action(5, 'Użytkownik się zalogował');

Co tu się dzieje? Komenda PERFORM wywołuje funkcję log_action, która wrzuca wpis do tabeli logs. Upewnij się, że rozumiesz: wynik wywołania funkcji jest ignorowany. Używamy jej tylko dla efektu, a nie dla zwracanych wartości.

Aktualizacja danych

Czasem PERFORM jest przydatny, gdy trzeba wykonać zapytanie zmieniające dane bez interesowania się jego wynikiem. Na przykład, zaktualizujmy status zamówienia w tabeli orders.

CREATE OR REPLACE FUNCTION update_order_status(order_id INT, new_status TEXT) RETURNS VOID AS $$
BEGIN
    UPDATE orders
    SET status = new_status
    WHERE id = order_id;
END;
$$ LANGUAGE plpgsql;

-- Używamy PERFORM do wywołania tej funkcji:
PERFORM update_order_status(101, 'Wysłane');

Tutaj update_order_status aktualizuje status zamówienia o identyfikatorze 101. Nie interesuje nas wynik zapytania SQL w funkcji, więc PERFORM to idealny wybór.

Uruchamianie operacji pomocniczych

Czasem funkcje zawierają mini-operacje, sprowadzone do "pomocniczej" logiki, która pomaga zakończyć złożony proces. Załóżmy, że chcemy wyczyścić cache po aktualizacji tabeli:

CREATE OR REPLACE FUNCTION clear_cache() RETURNS VOID AS $$
BEGIN
    DELETE FROM cache_table;
END;
$$ LANGUAGE plpgsql;

-- Wywołujemy ją w innej funkcji:
CREATE OR REPLACE FUNCTION update_product(product_id INT, new_price NUMERIC) RETURNS VOID AS $$
BEGIN
    UPDATE products
    SET price = new_price
    WHERE id = product_id;

    -- Czyścimy cache po zmianie danych:
    PERFORM clear_cache();
END;
$$ LANGUAGE plpgsql;

Tu jest magia: możesz wykonywać działania po kolei, używając PERFORM do wywoływania funkcji, których wynik cię kompletnie nie obchodzi.

Zadania praktyczne

Ogarnijmy kilka przykładów, jak PERFORM może ułatwić życie programiście.

Przykład 1: logowanie etapów procedury

Załóżmy, że mamy skomplikowaną procedurę obsługi płatności i musimy śledzić każdy jej etap, zapisując to do loga. Możemy zdefiniować funkcję log_stage do zapisywania info, a potem użyć PERFORM:

CREATE OR REPLACE FUNCTION log_stage(stage_name TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO process_logs(stage, log_time)
    VALUES (stage_name, NOW());
END;
$$ LANGUAGE plpgsql;

-- A tu przykład procedury:
CREATE OR REPLACE FUNCTION process_payment(payment_id INT) RETURNS VOID AS $$
BEGIN
    -- Logowanie startu
    PERFORM log_stage('Start przetwarzania płatności');

    -- Wykonujemy pierwszy etap
    UPDATE payments
    SET status = 'Przetwarzanie'
    WHERE id = payment_id;

    PERFORM log_stage('Zaktualizowano status płatności');

    -- Wykonujemy ostatni etap
    UPDATE payments
    SET status = 'Zakończono'
    WHERE id = payment_id;

    PERFORM log_stage('Płatność zakończona');
END;
$$ LANGUAGE plpgsql;

Tutaj log_stage jest wywoływana przez PERFORM do zapisywania stanu wykonania na każdym etapie procedury. To sprawia, że nasz kod jest łatwiejszy do debugowania.

Przykład 2: aktywacja powiadomień

Wyobraź sobie, że masz system powiadomień i musisz wysłać powiadomienie po każdej ważnej akcji. PERFORM może być użyty do wywołania funkcji odpowiedzialnej za to:

CREATE OR REPLACE FUNCTION send_notification(user_id INT, message TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO notifications (user_id, message, created_at)
    VALUES (user_id, message, NOW());
END;
$$ LANGUAGE plpgsql;

-- Używamy w procedurze:
CREATE OR REPLACE FUNCTION complete_task(task_id INT) RETURNS VOID AS $$
DECLARE
    user_id INT;
BEGIN
    -- Pobieramy autora zadania
    SELECT assigned_to INTO user_id
    FROM tasks
    WHERE id = task_id;

    -- Kończymy zadanie
    UPDATE tasks
    SET status = 'Zakończone'
    WHERE id = task_id;

    -- Wysyłamy powiadomienie
    PERFORM send_notification(user_id, 'Twoje zadanie zostało zakończone');
END;
$$ LANGUAGE plpgsql;

Tutaj PERFORM pozwala skupić się tylko na efekcie ubocznym — wysłaniu powiadomienia, ignorując wynik działania funkcji.

Przydatne wskazówki i typowe błędy

Kiedy używasz PERFORM, warto pamiętać o kilku rzeczach. Na przykład, PERFORM nie sprawdza, czy zapytanie zwróciło dane. To znaczy, że jeśli wynik funkcji albo zapytania SQL jest ważny dla logiki, lepiej użyć SELECT INTO. Zobacz przykład:

-- Potencjalny błąd
PERFORM some_function_that_must_return_value();

-- Poprawka
SELECT some_function_that_must_return_value() INTO some_variable;

Kolejny częsty błąd — używanie PERFORM tam, gdzie logicznie trzeba pobrać wynik zapytania, na przykład przy walidacji danych. W takich przypadkach oczywiście lepiej pobrać wynik i go sprawdzić.

W prawdziwych projektach komenda PERFORM pomaga robić funkcje i procedury prostsze, łatwiejsze do czytania i debugowania. W połączeniu z logowaniem (RAISE NOTICE) i wbudowanymi funkcjami diagnostycznymi PostgreSQL, jak current_query(), staje się ważnym narzędziem do budowania solidnych, zarządzalnych i czytelnych systemów.

2
Zadanie
SQL SELF, poziom 55, lekcja 3
Niedostępne
Wywołanie funkcji logującej z użyciem `PERFORM`
Wywołanie funkcji logującej z użyciem `PERFORM`
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION