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:
LOOP— universal dövrədir, hansı ki, açıq şəkildə dayandırılmayana qədər işləyir.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ə.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 $$;
counterdəyişəni hər iterasiyada artır.IF counter > 10 THEN EXIT;şərti, sayğac 10-u keçəndə dövrəni bitirir.- 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:
- Ədədlər aralığı üzrə.
- 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, id və price 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.
GO TO FULL VERSION