Əsas mövzuya keçməzdən əvvəl, gəlin ən çox rast gəlinən səhvlərə və çatışmazlıqlara baxaq. Axı SQL-də səhvlər hər bir developer üçün ağrıdır və adətən ən uyğun olmayan anda baş verir.
1. Sintaksis səhvləri: "IF-i bağlamağı unutdum"
Sintaksis səhvləri ən basic problemlərdir, amma düşündüyündən daha tez-tez baş verir. Məsələn, əgər IF şərt blokunu END IF; ilə bağlamağı unutmusansa, compiler dərhal səni qınayacaq.
Səhv nümunəsi:
CREATE OR REPLACE FUNCTION check_number(num INTEGER)
RETURNS TEXT AS $$
BEGIN
IF num > 0 THEN
RETURN 'Müsbət';
ELSE
RETURN 'Mənfi';
-- haradasa END IF; itib
END;
$$ LANGUAGE plpgsql;
Bu kodu işlətməyə çalışanda belə bir səhv alacaqsan: ERROR: syntax error at or near "END". Niyə? Çünki IF bloku açıq qalıb.
Belə səhvlərdən necə qaçmaq olar?
Həmişə kodun strukturunu aydın saxla. Bloku açanda (məsələn, IF), dərhal onun bağlanmasını da yaz. Düzgün nümunə belədir:
CREATE OR REPLACE FUNCTION check_number(num INTEGER)
RETURNS TEXT AS $$
BEGIN
IF num > 0 THEN
RETURN 'Müsbət';
ELSE
RETURN 'Mənfi';
END IF; -- bloku bağlamağı unutma
END;
$$ LANGUAGE plpgsql;
2. CASE-də bütün şərtlərin işlənməməsi: "Bəs heç birinə düşməsəm?"
CASE istifadə edəndə, həmişə ELSE şərtini əlavə et ki, gözlənilməz halları da tuta biləsən. Bu şərtin olmaması NULL qaytarılmasına səbəb ola bilər.
Səhv nümunəsi:
CREATE OR REPLACE FUNCTION grade_result(grade CHAR)
RETURNS TEXT AS $$
BEGIN
RETURN CASE grade
WHEN 'A' THEN 'Əla'
WHEN 'B' THEN 'Yaxşı'
WHEN 'C' THEN 'Orta'
-- Bəs grade = 'D' və ya başqa qiymət olsa?
END;
END;
$$ LANGUAGE plpgsql;
Əgər D dəyəri versən, funksiya NULL qaytaracaq və bu kodunda problem yarada bilər.
Düzgün variant:
CREATE OR REPLACE FUNCTION grade_result(grade CHAR)
RETURNS TEXT AS $$
BEGIN
RETURN CASE grade
WHEN 'A' THEN 'Əla'
WHEN 'B' THEN 'Yaxşı'
WHEN 'C' THEN 'Orta'
ELSE 'Naməlum qiymət' -- Qalan bütün halları tuturuq
END;
END;
$$ LANGUAGE plpgsql;
3. Sonsuz dövrlərlə bağlı problemlər: "Niyə server dondu?"
LOOP istifadə edəndə, dövrdən çıxmaq üçün şərt əlavə etməyi asanlıqla unuda bilərsən. Bu isə sonsuz icraya gətirib çıxarır:
Səhv nümunəsi:
CREATE OR REPLACE FUNCTION infinite_loop_demo()
RETURNS VOID AS $$
DECLARE
i INTEGER := 1;
BEGIN
LOOP
i := i + 1;
-- Çıxış şərti yoxdur!
END LOOP;
END;
$$ LANGUAGE plpgsql;
Bu kod serverin donmasına səbəb olacaq, çünki dövr heç vaxt bitməyəcək.
Necə düzəltmək olar:
EXIT ilə çıxış şərti əlavə et:
CREATE OR REPLACE FUNCTION finite_loop_demo()
RETURNS VOID AS $$
DECLARE
i INTEGER := 1;
BEGIN
LOOP
i := i + 1;
IF i > 10 THEN
EXIT; -- Çıxış şərti
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;
4. Dövrlərdə iterasiyaların ötürülməsi: "Bəs çatışmayan datalar necə oldu?"
CONTINUE istifadə edərək iterasiyaları ötürəndə, bütün davranış variantlarını nəzərə almamısansa, səhv baş verə bilər. Məsələn:
Səhv nümunəsi:
CREATE OR REPLACE FUNCTION skip_even()
RETURNS VOID AS $$
DECLARE
i INTEGER := 0;
BEGIN
WHILE i < 10 LOOP
i := i + 1;
IF i % 2 = 0 THEN
CONTINUE; -- Sadəcə cüt ədədləri ötürürük
END IF;
RAISE NOTICE 'Tək ədəd: %', i;
END LOOP;
END;
$$ LANGUAGE plpgsql;
Bəs bütün ədədlər cüt olsa? Server işləyəcək, amma heç bir nəticə görməyəcəksən.
Necə düzəltmək olar:
Bütün dataları düzgün işlədiyinə əmin ol və nəzarət üçün log əlavə et:
CREATE OR REPLACE FUNCTION skip_even_logging()
RETURNS VOID AS $$
DECLARE
i INTEGER := 0;
BEGIN
WHILE i < 10 LOOP
i := i + 1;
IF i % 2 = 0 THEN
RAISE NOTICE 'Cüt ədəd ötürüldü: %', i;
CONTINUE;
END IF;
RAISE NOTICE 'Tək ədəd: %', i;
END LOOP;
END;
$$ LANGUAGE plpgsql;
İndi hansı ədədlərin ötürüldüyünü görəcəksən.
5. Səhvlərin düzgün işlənməməsi: "Haradadır mənim RAISE EXCEPTION?"
RAISE EXCEPTION ilə səhvlərin işlənməsi güclü alətdir, amma onu səhv istifadə etmək asandır.
Səhv nümunəsi:
CREATE OR REPLACE FUNCTION calculate_square(num INTEGER)
RETURNS INTEGER AS $$
BEGIN
IF num < 0 THEN
RAISE 'Mənfi ədəd icazəli deyil!';
END IF;
RETURN num * num;
END;
$$ LANGUAGE plpgsql;
Bu kodda RAISE sintaksisi səhvdir (mesaj səviyyəsi yoxdur), ona görə də səhv çıxacaq.
Düzgün variant:
CREATE OR REPLACE FUNCTION calculate_square(num INTEGER)
RETURNS INTEGER AS $$
BEGIN
IF num < 0 THEN
RAISE EXCEPTION 'Mənfi ədəd icazəli deyil!';
END IF;
RETURN num * num;
END;
$$ LANGUAGE plpgsql;
6. Loglama zamanı səhvlər: "Niyə səhvlərim error_log-a yazılmır?"
error_log cədvəlinə düzgün yazmamaq INSERT INTO sorğularındakı səhvlərdən qaynaqlana bilər.
Səhv nümunəsi:
CREATE OR REPLACE FUNCTION log_error(err_msg TEXT)
RETURNS VOID AS $$
BEGIN
INSERT INTO error_log (error_message, error_time)
VALUES (err_msg, CURRENT_TIMESTAMP); -- Bəs sütunlarda səhv olsa?
END;
$$ LANGUAGE plpgsql;
Əgər error_log cədvəlində sütunun adı dəyişibsə (məsələn, error_msg olubsa), bu kodda səhv çıxacaq.
Necə qaçmaq olar:
Həmişə cədvəlin strukturunu yoxla və ya məlumatları idarə etmək üçün dəqiq sxem istifadə et.
7. Ümumi diqqətsizlik və "insan faktoru"
Səhvlər təkcə texniki olmur, bəzən də diqqətsizlikdən yaranır. Unudulmuş debug, istifadə olunmayan dəyişənlər və ya kodun formatlaşdırılmaması funksiyanı xaosa çevirə bilər.
Nümunə:
DECLARE
i INTEGER; -- Niyə, əgər dəyişən istifadə olunmur?
Düzəliş: Lazımsız kod hissələrini sil ki, kodun təmiz və başadüşülən olsun.
İndi PL/pgSQL-də ən çox rast gəlinən səhvlərdən qaçmağa hazırsan və kodun sənə daha çox sevinc, daha az başağrısı gətirəcək. Test etməyi, log yazmağı və vaxtında bug düzəltməyi unutma — bununla bir çox əsəb və müştəri zənglərinə qənaət edəcəksən!
GO TO FULL VERSION