Gəlin PL/pgSQL-i bir az daha dərindən öyrənək və onu daha aktiv istifadə etməyə başlayaq.
Kod bloku
PL/pgSQL-də kod bloku — dilin əsas tikinti elementidir. Belə deyə bilərik ki, bu, bizim funksiyalarımızın, prosedurlarımızın və başqa magiyanın dayandığı karkasdır. Blok bizə məntiqin icrasını, məlumatların işlənməsini, səhvlərin idarə olunmasını və bütün bunları bir "konteynerdə" təmin edir.
PL/pgSQL blokları strukturlaşdırılıb və üç əsas hissədən ibarətdir:
DECLARE: dəyişənlərin elan olunması (istəyə bağlıdır).BEGIN ... END: əsas icra bloku, burada məntiq işləyir.EXCEPTION: səhvlərin işlənməsi (istəyə bağlıdır).
Analogiya sevənlər üçün: təsəvvür elə bir yemək resepti yazırsan. Reseptin mətni bəlkə də inqrediyent siyahısı ilə başlayır, amma əsas magiya bişirmə prosesində baş verir. PL/pgSQL terminlərində:
DECLARE— inqrediyentlərin siyahısıdır (dəyişənlər).BEGIN ... END— burada qarışdırılır, qızardılır və bişirilir.EXCEPTION— nəsə yanarsa, nə etmək lazımdır planıdır.
PL/pgSQL blokunun sintaksisi
Əvvəlcə blokun ümumi strukturuna baxaq, yəni "skeletinə". Sonra ora ət (ya da vegetarian pendiri, əgər üstünlük verirsənsə) — konkret məntiq əlavə edəcəyik.
DO $$
DECLARE
-- Burada dəyişənlər elan olunur
student_count INT;
BEGIN
-- Burada məntiq icra olunur
SELECT COUNT(*) INTO student_count FROM students;
RAISE NOTICE 'Tələbələrin ümumi sayı: %', student_count;
EXCEPTION
-- Burada səhvlər işlənir
WHEN OTHERS THEN
RAISE NOTICE 'Səhv baş verdi.';
END;
$$;
Gəlin bunu addım-addım analiz edək.
DECLARE— burada dəyişənlərimizi elan edirik. Ən gözəl tərəfi odur ki, PL/pgSQL PostgreSQL-də olan demək olar ki, bütün data tiplərini dəstəkləyir — sadəINTEGER-dən tutmuş ekzotik JSONB-yə qədər. Dəyişəni elan etmək üçün onun adını, data tipini və lazım olsa ilkin dəyərini göstərirsən.
Nümunə:
DECLARE
student_name TEXT; -- Tələbənin adı üçün dəyişən
course_count INT := 0; -- İlkin dəyəri 0 qoyuruq
is_graduated BOOLEAN; -- Məntiqi dəyişən
Diqqət elə, dəyişənlər həm ilkin dəyərlə (məsələn, course_count), həm də onsuz ola bilər.
BEGIN ... END— əsas icra bloku.
Blokun bu hissəsi əsas məntiqin icrasına cavabdehdir. Burada sən:
- SQL sorğuları icra edə bilərsən (
SELECT,INSERTvə s.). - Məlumatlarla işləyə bilərsən.
- İdarəetmə konstruksiyalarından istifadə edə bilərsən (
IF,LOOPvə s.). RAISEilə debug mesajları çıxara bilərsən.
Nümunə:
BEGIN
SELECT COUNT(*) INTO student_count FROM students;
IF student_count > 0 THEN
RAISE NOTICE 'Bizdə tələbələr var!';
ELSE
RAISE NOTICE 'Tələbə tapılmadı.';
END IF;
END;
EXCEPTION— səhvlərin işlənməsi (istəyə bağlıdır).
Əgər blokun icrası zamanı səhv baş verərsə, EXCEPTION hissəsi onu tutmağa və nəsə faydalı bir şey etməyə imkan verir — məsələn, mesaj çıxarmaq və ya alternativ kod işlətmək.
Nümunə:
BEGIN
SELECT COUNT(*) INTO student_count FROM non_existing_table; -- Səhv!
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'Ups, nəsə düz getmədi!';
END;
Real nümunə: tələbələrin sayının hesablanması
İndi bütün hissələri birləşdirib real həyatda lazım ola biləcək bir nümunə yazaq. PL/pgSQL bloku yazacağıq ki, students cədvəlində tələbələrin sayını hesablayıb mesaj çıxarsın.
DO $$
DECLARE
total_students INT; -- Tələbələrin sayını saxlamaq üçün dəyişən
BEGIN
-- Tələbələrin sayını hesablayırıq
SELECT COUNT(*) INTO total_students FROM students;
-- Nəticə ilə mesaj çıxarırıq
RAISE NOTICE 'Tələbələrin sayı: %', total_students;
EXCEPTION
-- Mümkün səhvləri işləyirik, məsələn, cədvəl yoxdursa
WHEN OTHERS THEN
RAISE NOTICE 'Tələbələrin sayını hesablarkən səhv baş verdi.';
END;
$$;
Bu bloku çağıranda konsolda mesaj çıxacaq. Məsələn: Tələbələrin sayı: 42.
Dəyişənlərdən istifadə xüsusiyyətləri
Gəlin bir neçə vacib məqamı aydınlaşdıraq:
Dəyişənlərə dəyər mənimsətmək. Dəyişənə məlumat yazmaq üçün SELECT INTO operatorundan istifadə edə bilərsən:
SELECT COUNT(*) INTO total_students FROM students;
Dəyişənlərin ilkinləşdirilməsi. Əgər dəyişən elan olunanda ona dəyər verməmisənsə, onun dəyəri avtomatik olaraq NULL olacaq.
Məsələn:
DECLARE
my_var INT; -- Dəyəri NULL-dur
RECORD tipli dəyişənlər. Bu universal dəyişən tipidir, ora cədvəldən sətir yaza bilərsən. Nümunə:
DECLARE
student RECORD;
BEGIN
SELECT * INTO student FROM students WHERE id = 1;
RAISE NOTICE 'Tələbənin adı: %, Yaşı: %', student.name, student.age;
END;
Nümunə: tələbə üçün kursların sayının hesablanması
İndi praktik bir məsələni həll edək: tələbənin neçə kursa yazıldığını hesablayıb nəticəni çıxaraq.
DO $$
DECLARE
student_id INT := 1; -- Tələbənin ID-si
course_count INT; -- Kursların sayı üçün dəyişən
BEGIN
-- Kursların sayını hesablayırıq
SELECT COUNT(*) INTO course_count
FROM enrollments
WHERE student_id = student_id;
-- Mesaj çıxarırıq
RAISE NOTICE 'Tələbə ID % % kursa yazılıb.', student_id, course_count;
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'Tələbə ID % işlənərkən səhv baş verdi', student_id;
END;
$$;
Bu blok çevik işləyir: student_id-ni dəyişib müxtəlif tələbələr üçün neçə kurs olduğunu yoxlaya bilərsən.
Səhvlər və onların qarşısının alınması
Əgər içindəki PL/pgSQL artıq mikrodalğalı sobada kiçik hot-doq kimi partlayırsa, narahat olma — bu normaldır. Başlanğıcda tez-tez "tipik" səhvlərlə rastlaşmaq olur. Bir neçə nümunə:
Dəyişənin elan olunmaması. Əgər DECLARE ilə dəyişən elan etməyi unutsan, PL/pgSQL "dəyişən mövcud deyil" səhvini verəcək.
NULL dəyərindən istifadə cəhdi. Dəyişən elan olunubsa, amma ona dəyər verilməyibsə, nəticə NULL olacaq. Bu, gözlənilməz davranışlara səbəb ola bilər. Məsələn:
IF my_var = NULL THEN -- İŞLƏMƏYƏCƏK!
IS NULL istifadə et:
IF my_var IS NULL THEN
EXCEPTION hissəsinin səhv istifadəsi. Bəzən proqramçılar bütün səhvləri (WHEN OTHERS) tuturlar, amma nə etmək lazım olduğunu yazmırlar. Bu, real problemi gizlədə bilər. Daha yaxşısı, səhv mesajını qeyd etməkdir:
RAISE NOTICE 'Səhv: %', SQLERRM;
GO TO FULL VERSION