Bu gün funksiyaların yaradılmasında tipik səhvləri, onların səbəblərini və necə düzəldiləcəyini müzakirə edəcəyik. Axı, yalnız debug edərək əsl proqramçı öz sənətini öyrənir — coding! Let's debug it!
Funksiya yaratmaq, xüsusilə PL/pgSQL öyrənməyə yeni başlayanlar üçün bir az çətin görünə bilər. Hətta ən təcrübəli PostgreSQL developer-lar belə bəzən "daşlara" rast gəlirlər. Gəlin bunları bir-bir analiz edək.
1. RETURNS açar sözünün unudulması
PL/pgSQL funksiyaların təsvirində çox ciddi davranır. Ən çox rast gəlinən yanlışlardan biri — funksiyanın hansı data type qaytarmalı olduğunu göstərməməyi unutmaqdır. Məsələn:
-- Səhv: RETURNS açar sözü yoxdur
CREATE FUNCTION incorrect_function() AS $$
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
PostgreSQL başa düşməyəcək ki, bu funksiya nə qaytarmalıdır. RETURNS sintaksisin məcburi hissəsidir və qaytarılan data type-ı göstərir (məsələn, RETURNS INT, RETURNS TEXT və ya hətta RETURNS VOID).
Düzəliş: RETURNS açar sözünü və data type-ı əlavə et:
CREATE FUNCTION correct_function() RETURNS INT AS $$
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
2. RETURN olmadan nəticə qaytarmaq cəhdi
Yeni başlayan developer-lar tez-tez unudurlar ki, PL/pgSQL-də nəticə qaytarmaq üçün mütləq RETURN operatorundan istifadə etmək lazımdır. Məsələn:
-- Səhv: RETURN yoxdur
CREATE FUNCTION missing_return() RETURNS TEXT AS $$
BEGIN
'Salam, Dünya!'; -- Sadəcə string, amma qaytarılmır
END;
$$ LANGUAGE plpgsql;
Burada 'Salam, Dünya!' sadəcə yazılıb, amma qaytarılmır. PostgreSQL bunu nəticə kimi görmür və error atacaq.
Düzəliş: aydın şəkildə RETURN operatorunu əlavə et:
CREATE FUNCTION fixed_return() RETURNS TEXT AS $$
BEGIN
RETURN 'Salam, Dünya!';
END;
$$ LANGUAGE plpgsql;
3. Deklarasiya olunmamış dəyişənə data yazmaq cəhdi
PL/pgSQL-də dəyişəni istifadə etməzdən əvvəl DECLARE blokunda elan etmək lazımdır. Məsələn:
-- Səhv: my_var dəyişəni elan olunmayıb
CREATE FUNCTION missing_variable() RETURNS VOID AS $$
BEGIN
my_var := 'Salam, Dünya!';
END;
$$ LANGUAGE plpgsql;
PostgreSQL my_var dəyişəninin mövcudluğundan xəbərsizdir, çünki o, DECLARE blokunda elan olunmayıb.
Düzəliş: dəyişənləri həmişə DECLARE-də elan et:
CREATE FUNCTION declared_variable() RETURNS VOID AS $$
DECLARE
my_var TEXT;
BEGIN
my_var := 'Salam, Dünya!';
END;
$$ LANGUAGE plpgsql;
4. VOID tipinin düzgün istifadə olunmaması
VOID tipi göstərir ki, funksiya heç bir data qaytarmır. Bəzən developer-lar VOID tipli funksiyada RETURN istifadə etməyə çalışırlar və bu da error verir:
-- Səhv: VOID tipli funksiyada RETURN
CREATE FUNCTION void_example() RETURNS VOID AS $$
BEGIN
RETURN 1; -- Dəyər qaytarmaq olmaz
END;
$$ LANGUAGE plpgsql;
VOID tipli funksiyalar dəyər qaytarmamalıdır. RETURN operatorundan istifadə etmək olar, amma dəyərsiz.
Düzəliş: ya RETURN-u sil, ya da dəyərsiz yaz:
CREATE FUNCTION correct_void() RETURNS VOID AS $$
BEGIN
-- Sadəcə əməliyyatlar aparılır
RAISE NOTICE 'Bu funksiya heç nə qaytarmır';
RETURN; -- Funksiyanı bitirir
END;
$$ LANGUAGE plpgsql;
5. Debug üçün RAISE-in səhv istifadəsi
PL/pgSQL-də debug çox vaxt RAISE NOTICE operatoru ilə edilir. Amma yanlış format və dəyişənlərdən istifadə error-a səbəb ola bilər.
Məsələn:
-- Səhv: yanlış format
CREATE FUNCTION debug_example() RETURNS VOID AS $$
BEGIN
RAISE NOTICE 'Dəyər: %'; -- Dəyişən yoxdur
END;
$$ LANGUAGE plpgsql;
RAISE operatoru gözləyir ki, %-dən sonra dəyişən və ya dəyər gələcək. Əgər % boş qalsa, PostgreSQL error verəcək.
Düzəliş: dəyişən və ya dəyərləri düzgün göstər:
CREATE FUNCTION fixed_debug() RETURNS VOID AS $$
DECLARE
my_var TEXT := 'PostgreSQL';
BEGIN
RAISE NOTICE 'Dəyər: %', my_var; -- Dəyişən göstərilib
END;
$$ LANGUAGE plpgsql;
6. Dəyişən və sütun adlarının toqquşması
Əgər dəyişənin adı sütunun adı ilə üst-üstə düşürsə, bu gözlənilməz nəticələrə gətirib çıxara bilər. Məsələn:
-- Səhv: dəyişən və sütun adının konflikti
CREATE FUNCTION name_conflict() RETURNS TEXT AS $$
DECLARE
name TEXT;
BEGIN
SELECT name INTO name FROM students LIMIT 1; -- Hansı name istifadə olunur?
RETURN name;
END;
$$ LANGUAGE plpgsql;
PL/pgSQL-də dəyişən adı ilə sütun adı üst-üstə düşəndə, dəyişən üstünlük təşkil edir.
Düzəliş: cədvəl üçün alias istifadə et və ya adların üst-üstə düşməsindən qaç:
CREATE FUNCTION fixed_conflict() RETURNS TEXT AS $$
DECLARE
student_name TEXT;
BEGIN
SELECT s.name INTO student_name FROM students s LIMIT 1;
RETURN student_name;
END;
$$ LANGUAGE plpgsql;
7. Dövrədə (loop-da) sorğuların səhv icrası
Loop-larda SQL-sorğuları icra edərkən tez-tez səhvlər olur. Məsələn:
-- Səhv: loop-da yanlış sorğu
CREATE FUNCTION cycle_error() RETURNS VOID AS $$
BEGIN
FOR rec IN SELECT * FROM students LOOP
EXECUTE 'UPDATE students SET active = TRUE WHERE id = ' || rec.id;
END LOOP;
END;
$$ LANGUAGE plpgsql;
SQL-injection... Təhlükə! SQL-sorğular üçün string birləşdirmək — pis praktikadır. Bu, təhlükəsiz deyil.
Düzəliş üçün parametrlərdən istifadə et:
CREATE FUNCTION safe_cycle() RETURNS VOID AS $$
BEGIN
FOR rec IN SELECT * FROM students LOOP
EXECUTE 'UPDATE students SET active = TRUE WHERE id = $1' USING rec.id;
END LOOP;
END;
$$ LANGUAGE plpgsql;
8. Data type-larla bağlı səhvlər
Səhv nümunəsi:
-- Səhv: data type uyğun gəlmir
CREATE FUNCTION type_error() RETURNS INT AS $$
DECLARE
my_var TEXT := 'not_a_number';
BEGIN
RETURN my_var; -- INT əvəzinə TEXT qaytarılır, error
END;
$$ LANGUAGE plpgsql;
PostgreSQL INT gözləyir, amma TEXT alır. Data type-ların uyğunluğu ciddi yoxlanılır.
Düzəliş? Data type-ları uyğunlaşdır və ya explicit conversion et:
CREATE FUNCTION type_correct() RETURNS INT AS $$
DECLARE
my_var TEXT := '42';
BEGIN
RETURN my_var::INT; -- Text-i rəqəmə çeviririk
END;
$$ LANGUAGE plpgsql;
Ən yaxşı praktikalar və məsləhətlər
- Çətin funksiyaları kiçik hissələrə böl. Bu, debug və test etməyi asanlaşdırır.
- Funksiyalarda comment-lərdən istifadə et — çətin əməliyyatları izah etmək üçün.
- Funksiyaları əvvəlcə kiçik datalar üzərində test et, real cədvəllərdə istifadə etməzdən əvvəl.
RAISE NOTICEilə debug et, icra prosesini başa düşmək üçün.- SQL-injection-lardan qaç: sorğular üçün parametrlərdən istifadə et.
-- Debug üçün RAISE istifadə olunur
DO $$
DECLARE
total_students INT;
BEGIN
SELECT COUNT(*) INTO total_students FROM students;
RAISE NOTICE 'Cəmi tələbə: %', total_students; -- Debug mesajı
END;
$$;
Bu məsləhətlər bir çox başağrısından qaçmağa və PL/pgSQL "daşlarını" birdəfəlik məhv etməyə kömək edəcək!
GO TO FULL VERSION