CodeGym /Kurslar /SQL SELF /Dövrələrdən istifadə: LOOP, FOR, WHILE PL/pgSQL-də

Dövrələrdən istifadə: LOOP, FOR, WHILE PL/pgSQL-də

SQL SELF
Səviyyə , Dərs
Mövcuddur

Dövrələr kod blokunu bir neçə dəfə ardıcıl icra etməyə imkan verir, ta ki, müəyyən bir şərt yerinə yetirilənə qədər və ya hansısa məlumat dəstində iterasiya başa çatana qədər. Bu, tapşırıqları avtomatlaşdırmaq, böyük həcmdə məlumatları işləmək və ya təkrarlanan əməliyyatları yerinə yetirmək üçün çox faydalıdır.

Təsəvvür elə ki, sən əl ilə bütün uşaqlara konfet paylamalısan. Bu, tam xaos olardı! Onun əvəzinə, sən uşaqların siyahısından keçib, hər birinə növbə ilə konfet verə bilərsən. Bu ssenaridə "siyahıdan keçmək" — dövrədir.

PostgreSQL-də bir neçə növ dövrə dəstəklənir:

  1. LOOP — universal dövrədir, hansı ki, açıq şəkildə dayandırılmayana qədər işləyir.
  2. FOR — müəyyən sayda iterasiya üçün, ədədlər aralığında və ya sorğunun nəticəsində işləyən dövrə.
  3. WHILE — şərt doğru olduğu müddətdə işləyən dövrə.

Gəlin hər növü ayrıca nəzərdən keçirək.

Sonsuz dövrə: LOOP

LOOP — PL/pgSQL-də dövrənin əsas formasıdır, hansı ki, kod blokunu təkrar-təkrar icra edir. Bu dövrə sonsuz işləyir və onu əl ilə EXIT əmri ilə dayandırmaq lazımdır.

Sintaksis:

LOOP
    -- Sənin kodun burda
END LOOP;

Bir nümunə göstərək. LOOP ilə 1-dən 10-a qədər ədədlərin cəmini hesablayaq:

DO $$
DECLARE
    counter INT := 1;
    sum INT := 0;
BEGIN
    LOOP
        sum := sum + counter; -- cari sayğac dəyərini əlavə edirik
        counter := counter + 1; -- sayğacı artırırıq

        -- Əgər sayğac 10-dan böyükdürsə, dövrəni bitiririk
        IF counter > 10 THEN
            EXIT;
        END IF;
    END LOOP;

    RAISE NOTICE '1-dən 10-a qədər ədədlərin cəmi: %', sum;
END $$;
  1. counter dəyişəni hər iterasiyada artır.
  2. IF counter > 10 THEN EXIT; şərti, sayğac 10-u keçəndə dövrəni bitirir.
  3. Sonda ədədlərin cəmi çıxarılır.

Aralıq və ya məlumat dəsti üzrə dövrə: FOR

İkinci dövrə tipi, FOR, aşağıdakılar üçün istifadə olunur:

  1. Ədədlər aralığı üzrə.
  2. SQL-sorğunun nəticəsi üzrə.

Ədədlər aralığı üzrə dövrə

Sintaksis:

FOR variable IN [REVERSE] start..end LOOP
    -- Sənin kodun burda
END LOOP;

1-dən 5-ə qədər ədədləri çıxaraq:

DO $$
BEGIN
    FOR i IN 1..5 LOOP
        RAISE NOTICE 'Cari dəyər: %', i;
    END LOOP;
END $$;

Tərs ardıcıllıqla nümunə:

DO $$
BEGIN
    FOR i IN REVERSE 5..1 LOOP
        RAISE NOTICE 'Tərs ardıcıllıq: %', i;
    END LOOP;
END $$;

SQL-sorğunun nəticəsi üzrə dövrə

Bu variant cədvəlin sətirlərini işləmək üçün faydalıdır.

Sintaksis:

FOR variable IN QUERY (SELECT ...) LOOP
    -- Sənin kodun burda
END LOOP;

students cədvəlinin sətirləri üzrə iterasiya nümunəsi:

DO $$
DECLARE
    student_name TEXT;
BEGIN
    FOR student_name IN QUERY (SELECT name FROM students) LOOP
        RAISE NOTICE 'Salam, %!', student_name;
    END LOOP;
END $$;

Şərtli dövrə: WHILE

WHILE verilmiş şərt doğru olduğu müddətdə işləyir.

Sintaksis:

WHILE şərt LOOP
    -- Sənin kodun burda
END LOOP;

Gəlin WHILE ilə 1-dən 10-a qədər ədədlərin cəmini hesablayaq:

DO $$
DECLARE
    counter INT := 1;
    sum INT := 0;
BEGIN
    WHILE counter <= 10 LOOP
        sum := sum + counter;
        counter := counter + 1;
    END LOOP;

    RAISE NOTICE '1-dən 10-a qədər ədədlərin cəmi: %', sum;
END $$;

Həyatdan nümunələr

İndi ki, dövrələrin əsaslarını başa düşdük, gəlin onların tətbiqinə real nümunələrə baxaq.

Nümunə 1: vurma cədvəlini generasiya etmək

DO $$
DECLARE
    i INT;
    j INT;
BEGIN
    FOR i IN 1..5 LOOP
        FOR j IN 1..5 LOOP
            RAISE NOTICE '% x % = %', i, j, i * j;
        END LOOP;
    END LOOP;
END $$;

Nümunə 2: sorğu nəticələri üzrə iterasiya. Tutaq ki, bizdə products cədvəli var, idprice sahələri ilə. Bütün qiymətləri 10% artıraraq yeniləyək.

DO $$
DECLARE
    prod RECORD;
BEGIN
    FOR prod IN QUERY (SELECT id, price FROM products) LOOP
        UPDATE products
        SET price = prod.price * 1.1
        WHERE id = prod.id;
    END LOOP;
END $$;

Tipik səhvlər və onlardan necə qaçmaq olar

LOOP və ya WHILE-da sonsuz dövrə. Əgər çıxış şərtini (EXIT və ya WHILE-da düzgün şərt) əlavə etməyi unutsan, dövrə heç vaxt bitməyəcək. Bu, sanki əyləcsiz maşın sürmək kimidir.

Sorğu nəticəsi üzrə iterasiyada səhv. Əgər nəticə məlumatlarının strukturu gözlənilən kimi deyilsə, FOR IN QUERY dövrəsində səhv ala bilərsən.

Dövrələrdə optimal olmayan sorğular. Məsələn, hər iterasiyada UPDATE işlətmək icranı çox yavaşlada bilər. Belə hallarda bir SQL-sorğu ilə işi həll etmək daha yaxşıdır.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION