CodeGym /Kursy /SQL SELF /Przerywanie i kontynuacja pętli: EXIT, CONTINUE

Przerywanie i kontynuacja pętli: EXIT, CONTINUE

SQL SELF
Poziom 51 , Lekcja 2
Dostępny

Czasem w pętli wszystko idzie zgodnie z planem — aż pojawi się powód, żeby zatrzymać się wcześniej. Na szczęście PL/pgSQL daje nam wygodne narzędzia, żeby tym sterować.

Przerywanie pętli za pomocą EXIT

Czasami trzeba zakończyć pętlę wcześniej, zanim sama dojdzie do końca. Może to być spowodowane np. znalezieniem potrzebnej wartości, wykryciem błędu albo spełnieniem jakiegoś warunku. W takich sytuacjach używamy EXIT.

EXIT to sposób, żeby "powiedzieć" pętli: "Wystarczy, zrobiłeś swoje, czas się zatrzymać".

Składnia EXIT jest mega prosta:

EXIT WHEN warunek;

Tutaj kluczowa fraza WHEN wskazuje, przy jakim warunku pętla zostanie zakończona. Jeśli warunek nie jest podany, EXIT po prostu natychmiast kończy bieżącą pętlę.

Przykład: zakończenie pętli, gdy znaleziono określoną wartość

Załóżmy, że mamy kolumnę z numerami studentów i chcemy znaleźć studenta z konkretnym identyfikatorem. Jak tylko student zostanie znaleziony, pętla powinna się zakończyć.

DO $$
DECLARE
    student_id INT;
BEGIN
    FOR student_id IN 1..100 LOOP
        RAISE NOTICE 'Sprawdzam student ID: %', student_id;

        -- Jeśli znaleźliśmy właściwego studenta, kończymy pętlę
        IF student_id = 42 THEN
            RAISE NOTICE 'Student z ID 42 znaleziony!';
            EXIT;
        END IF;
    END LOOP;
END $$;

W tym przykładzie pętla przechodzi przez liczby od 1 do 100, sprawdzając każdego "studenta". Jak tylko ID 42 zostanie znalezione, pętla wypisuje komunikat i kończy się.

Pomijanie iteracji za pomocą CONTINUE

Są sytuacje, gdy w pętli trzeba pominąć niektóre iteracje, ale kontynuować kolejne. To szczególnie przydatne, jeśli chcesz zignorować "niepotrzebne" dane albo pominąć kroki dla specyficznych warunków.

CONTINUE mówi: "Ok, ten warunek nam nie pasuje, po prostu przechodzimy do następnej iteracji".

CONTINUE działa na tej samej zasadzie co EXIT, tylko zamiast kończyć pętlę, pomija bieżącą iterację:

CONTINUE WHEN warunek;

Jeśli warunek jest spełniony, bieżąca iteracja się kończy i przechodzimy do następnej.

Przykład: pomijanie liczb parzystych

W tym przykładzie będziemy przechodzić przez liczby od 1 do 10, ale ignorować liczby parzyste, wypisując tylko nieparzyste.

DO $$
DECLARE
    num INT;
BEGIN
    FOR num IN 1..10 LOOP
        -- Pomijamy liczby parzyste
        IF num % 2 = 0 THEN
            CONTINUE;
        END IF;

        RAISE NOTICE 'Liczba nieparzysta: %', num;
    END LOOP;
END $$;

Tutaj CONTINUE pomija wszystkie iteracje, gdzie num % 2 = 0 (czyli liczba jest parzysta). W efekcie w logu pojawią się tylko liczby nieparzyste.

Kombinowanie EXIT i CONTINUE

EXIT i CONTINUE można używać razem, żeby bardziej elastycznie sterować pętlą. Na przykład możesz pomijać niepotrzebne iteracje za pomocą CONTINUE, ale kończyć całą pętlę, jeśli znajdziesz coś ważnego.

Oto przykład, gdzie pomijamy wszystkie liczby podzielne przez 3, ale kończymy pętlę, jak tylko dojdziemy do liczby 15.

DO $$
DECLARE
    num INT;
BEGIN
    FOR num IN 1..20 LOOP
        -- Pomijamy liczby podzielne przez 3
        IF num % 3 = 0 THEN
            CONTINUE;
        END IF;

        -- Kończymy pętlę, jeśli liczba to 15
        IF num = 15 THEN
            RAISE NOTICE 'Zatrzymuję się na liczbie %', num;
            EXIT;
        END IF;

        RAISE NOTICE 'Aktualna liczba: %', num;
    END LOOP;
END $$;

Tutaj pętla działa tak:

  • Liczby podzielne przez 3 są pomijane (CONTINUE).
  • Jeśli liczba to 15, pętla się kończy (EXIT).
  • Wszystkie pozostałe liczby są wypisywane.

Bardziej zaawansowany przykład: pomijanie niepoprawnych danych i zakończenie przy krytycznym błędzie

Teraz wyobraźmy sobie bardziej realne zadanie. Chcemy przetworzyć listę studentów, sprawdzając ich dane. Niepoprawne wpisy będziemy pomijać, a w przypadku "krytycznego błędu" przerywać przetwarzanie.

DO $$
DECLARE
    student RECORD;
BEGIN
    FOR student IN
        SELECT * FROM students
    LOOP
        -- Pomijamy wpisy z niepoprawnymi danymi
        IF student.name IS NULL THEN
            RAISE NOTICE 'Pomijam studenta z ID %: Brak imienia', student.id;
            CONTINUE;
        END IF;

        -- Kończymy pętlę przy krytycznym błędzie
        IF student.status = 'ERROR' THEN
            RAISE EXCEPTION 'Krytyczny błąd dla studenta ID %', student.id;
            EXIT; -- Ta linia jest właściwie zbędna, bo RAISE EXCEPTION kończy wykonanie.
        END IF;

        -- Przetwarzanie wpisu
        RAISE NOTICE 'Przetwarzam studenta: %', student.name;
    END LOOP;
END $$;

W tym przykładzie CONTINUE pomaga pominąć studentów bez imienia, a EXIT (razem z RAISE EXCEPTION) kończy pętlę przy poważnym błędzie.

Praktyczne wskazówki i typowe błędy

Nie zapominaj o logice warunków. Złe użycie wyrażeń warunkowych w EXIT WHEN albo CONTINUE WHEN może prowadzić do nieoczekiwanego zachowania. Na przykład pętla może skończyć się za wcześnie albo pominąć ważne dane.

Nadmierne używanie CONTINUE. Jeśli twój kod jest pełen sprawdzeń z CONTINUE, może warto przemyśleć logikę pętli, żeby była prostsza.

Nie myl EXIT i RETURN. EXIT kończy tylko bieżącą pętlę, a RETURN kończy wykonanie całej funkcji.

Uważaj na nieskończone pętle. Jeśli używasz pętli LOOP bez jasnego warunku zakończenia, zapomnisz o EXIT i twoja pętla może działać w nieskończoność.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION