Bir neçə səviyyə əvvəl artıq PostgreSQL-də prosedurlar və funksiyalar mövzusuna toxunmuşduq. İndi isə gəlin onları daha dərindən öyrənək.
Funksiyalar və prosedurlar təkbaşına işləyə bilər, amma əksər hallarda onların qarşılıqlı əlaqəsi bütün sistemin uğurunu müəyyən edir. Əsas rahatlıq ondadır ki, funksiyaları bir-birinin içində çağırmaq, məlumat ötürmək və hətta nəticəni almaq mümkündür.
Funksiyalar vs Prosedurlar: fərq nədədir?
Gəlin yadımıza salaq, PostgreSQL-də funksiyalar prosedurlardan nə ilə fərqlənir:
Funksiyalar (
FUNCTION):- Dəyərlər qaytarır.
- Onları
SELECT-də istifadə etmək olar. - Çox vaxt hesablamalar və ya məlumat çevirmələri üçün istifadə olunur.
Prosedurlar (
PROCEDURE):- Dəyərləri birbaşa qaytarmır.
- Məlumat əlavə etmək, yeniləmək və ya silmək kimi əməliyyatlar üçün istifadə olunur.
CALLəmri ilə çağırılır.
Funksiyalar arasında məlumat ötürülməsi
Praktikaya keçək, funksiyadan prosedura və ya funksiyadan funksiyaya məlumat ötürülməsinin əsas nümunəsindən başlayaq. Əslində, funksiyalar arasında məlumat ötürülməsi parametrlər və qaytarılan dəyərlər vasitəsilə baş verir.
Bir funksiyanın başqa bir funksiyanın içində çağırılması belə görünür:
CREATE OR REPLACE FUNCTION get_student_name(student_id INT)
RETURNS TEXT AS $$
DECLARE
student_name TEXT;
BEGIN
-- Student ID-ə görə tələbənin adını çıxarırıq
SELECT name INTO student_name FROM students WHERE id = student_id;
-- Adı qaytarırıq
RETURN student_name;
END;
$$ LANGUAGE plpgsql;
Bu funksiyanı başqa bir funksiyanın içində çağırmaq olar:
CREATE OR REPLACE FUNCTION welcome_student(student_id INT)
RETURNS TEXT AS $$
DECLARE
message TEXT;
BEGIN
-- Başqa funksiyanın köməyi ilə tələbənin adını alırıq
message := 'Xoş gəldin, ' || get_student_name(student_id) || '!';
-- Salamlamanı qaytarırıq
RETURN message;
END;
$$ LANGUAGE plpgsql;
get_student_namefunksiyası tələbənin identifikatoruna (student_id) görə adını qaytarır.- Başqa funksiyada —
welcome_student— bu ad salam mesajı yaratmaq üçün istifadə olunur.
Qeyd: SELECT INTO ilə məlumat çıxaranda nəticə PL/pgSQL dəyişənində saxlanılır.
Funksiyalardan prosedurların çağırılması nümunəsi
İndi isə gəlin baxaq, funksiyadan proseduru necə çağırmaq olar. Tutaq ki, bizdə tələbənin sistemə giriş vaxtını qeyd edən prosedur var:
CREATE OR REPLACE PROCEDURE log_student_entry(student_id INT)
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO log_entries(student_id, entry_time)
VALUES (student_id, NOW());
END;
$$;
İndi bu proseduru funksiyanın içində çağıracağıq, burada giriş qeyd olunacaq və mesaj qaytarılacaq:
CREATE OR REPLACE FUNCTION student_login(student_id INT)
RETURNS TEXT AS $$
BEGIN
-- Log üçün proseduru çağırırıq
CALL log_student_entry(student_id);
-- Mesajı qaytarırıq
RETURN 'Tələbənin girişi uğurla qeyd olundu.';
END;
$$ LANGUAGE plpgsql;
Praktik qarşılıqlı əlaqə nümunələri
Nümunə 1: yekun məbləğin hesablanması və sifarişin loglanması
Təsəvvür et ki, sən online-sifariş sistemi ilə işləyirsən. Sifarişin yekun məbləğini hesablamaq üçün belə bir funksiya var:
CREATE OR REPLACE FUNCTION calculate_order_total(order_id INT)
RETURNS NUMERIC AS $$
DECLARE
total NUMERIC;
BEGIN
-- Sifarişin bütün mövqelərini toplayırıq
SELECT SUM(price * quantity) INTO total
FROM order_items
WHERE order_id = order_id;
RETURN total;
END;
$$ LANGUAGE plpgsql;
Sifarişin yekun məbləğini saxlamaq üçün prosedurdan istifadə olunur:
CREATE OR REPLACE PROCEDURE log_order_total(order_id INT, total NUMERIC)
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO order_totals(order_id, total)
VALUES (order_id, total);
END;
$$;
İndi onları birləşdirək:
CREATE OR REPLACE FUNCTION process_order(order_id INT)
RETURNS TEXT AS $$
DECLARE
total NUMERIC;
BEGIN
-- Yekun məbləği hesablamaq üçün funksiyanı çağırırıq
total := calculate_order_total(order_id);
-- Yekun məbləği prosedur vasitəsilə loglayırıq
CALL log_order_total(order_id, total);
RETURN 'Sifariş uğurla emal olundu.';
END;
$$ LANGUAGE plpgsql;
Nümunə 2: tələbənin maksimum reytinqinin alınması və profilin yenilənməsi
Maksimum reytinqi almaq üçün funksiya:
CREATE OR REPLACE FUNCTION get_highest_rating(student_id INT)
RETURNS INT AS $$
DECLARE
max_rating INT;
BEGIN
-- Tələbənin maksimum reytinqini tapırıq
SELECT MAX(rating) INTO max_rating
FROM ratings
WHERE student_id = student_id;
RETURN max_rating;
END;
$$ LANGUAGE plpgsql;
Tələbə profilini yeniləmək üçün prosedur:
CREATE OR REPLACE PROCEDURE update_student_profile(student_id INT, max_rating INT)
LANGUAGE plpgsql
AS $$
BEGIN
UPDATE students
SET highest_rating = max_rating
WHERE id = student_id;
END;
$$;
Bu əməliyyatları çağıran funksiya:
CREATE OR REPLACE FUNCTION refresh_student_profile(student_id INT)
RETURNS TEXT AS $$
DECLARE
max_rating INT;
BEGIN
-- Maksimum reytinqi alırıq
max_rating := get_highest_rating(student_id);
-- Tələbə profilini yeniləyirik
CALL update_student_profile(student_id, max_rating);
RETURN 'Profil uğurla yeniləndi.';
END;
$$ LANGUAGE plpgsql;
Qarşılıqlı əlaqədə tipik səhvlər
Ən çox rast gəlinən səhvlərdən biri — funksiya və prosedur arasında məlumat tiplərinin uyğun gəlməməsidir. Məsələn, əgər prosedur NUMERIC tipində parametr gözləyirsə, amma sən INTEGER ötürürsənsə, PostgreSQL tip uyğunsuzluğu barədə xəbərdarlıq edəcək. Həmişə yoxla ki, məlumat tipləri uyğun gəlsin.
Başqa bir səhv — funksiyaların bir-birini dövrü şəkildə çağırmasıdır: funksiya A funksiyanı B çağırır, o isə yenidən A-nı çağırır. Bu, sonsuz çağırışa və sistemin çökməsinə gətirib çıxarır.
Praktik əhəmiyyət
Bəs bizə belə qarşılıqlı əlaqə niyə lazımdır? Real həyatda funksiyalar və prosedurlar mürəkkəb sistemlərin "konstruksiya blokları" kimi işləyir. Onlar kodu müstəqil hissələrə bölməyə imkan verir, bu da debug, təkrar istifadə və test etməni asanlaşdırır. Məsələn:
- Müsahibədə səndən proseduru çağıran funksiya yazmağı istəyə bilərlər. Qarşılıqlı əlaqə bacarığını göstərmək böyük üstünlükdür.
- Real tətbiqlərin hazırlanmasında, məsələn, internet-mağazalar, log sistemləri və ya CRM-lərdə funksiyalar və prosedurlar vasitəsilə funksionallığı düzgün təşkil etmək kodu xeyli sadələşdirir.
Funksiyalar və prosedurlar arasında qarşılıqlı əlaqəni daha dərindən öyrənmək üçün PL/pgSQL üzrə rəsmi sənədləşməyə baxa bilərsən.
GO TO FULL VERSION