PostgreSQL функц бичих
Та нэг давтагдах тооцоог олон газар бичиж байна уу? PostgreSQL-д өөрийн функц бичиж, SQL асуулгаас дуудаж болно. Хөгжүүлэгчид ихэвчлэн нарийн бизнесийн логикийг функцэд оруулж, application layer-аас хамгаалдаг. Энэ хичээлд PL/pgSQL — PostgreSQL-н хамгийн нийтлэг функцийн хэл — сурна.
Энгийн SQL функц
Параметр авч нэг утга буцаадаг хамгийн энгийн функц:
-- Нэр ба овгийг нийлүүлэх функц
CREATE OR REPLACE FUNCTION full_name(first_name TEXT, last_name TEXT)
RETURNS TEXT
LANGUAGE SQL
AS $$
SELECT first_name || ' ' || last_name;
$$;
-- Дуудах
SELECT full_name('Болд', 'Баатар');
-- Үр дүн: Болд Баатар
-- Хүснэгтийн баганатай хамт ашиглах
SELECT full_name(first_name, last_name) AS бүтэн_нэр, email
FROM users;
$$ тэмдэглэгээ нь функцийн биеийг хязгаарладаг. CREATE OR REPLACE нь функц байгаа бол шинэчилж, байхгүй бол шинээр үүсгэнэ.
PL/pgSQL функц — нарийн логик
PL/pgSQL нь нөхцөл шалгалт, давталт, хувьсагч зэрэг боломж агуулсан процедур хэл юм:
-- XP-с level тооцоолох функц
CREATE OR REPLACE FUNCTION get_level(xp INT)
RETURNS INT
LANGUAGE plpgsql
AS $$
DECLARE
level INT;
BEGIN
IF xp < 100 THEN
level := 1;
ELSIF xp < 500 THEN
level := 2;
ELSIF xp < 1500 THEN
level := 3;
ELSIF xp < 4000 THEN
level := 4;
ELSE
level := 5;
END IF;
RETURN level;
END;
$$;
-- Дуудах
SELECT get_level(250); -- Үр дүн: 2
SELECT get_level(2000); -- Үр дүн: 4
DECLARE хэсэгт хувьсагч зарлана. BEGIN ... END хооронд логик бичнэ. RETURN үр дүн буцаана.
Хүснэгт буцаадаг функц (RETURNS TABLE)
Функц зөвхөн нэг утга биш, бүх хүснэгт буцааж болно:
-- Хэлтсийн ажилчдыг буцаадаг функц
CREATE OR REPLACE FUNCTION get_employees_by_dept(dept_name TEXT)
RETURNS TABLE(
нэр TEXT,
имэйл TEXT,
цалин NUMERIC,
ажилласан_жил INT
)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY
SELECT
e.full_name,
e.email,
e.salary,
DATE_PART('year', AGE(NOW(), e.hired_at))::INT
FROM employees e
JOIN departments d ON e.department_id = d.id
WHERE d.name = dept_name
ORDER BY e.salary DESC;
END;
$$;
-- Хүснэгт шиг дуудах
SELECT * FROM get_employees_by_dept('Инженер');
-- WHERE нэмж болно
SELECT нэр, цалин
FROM get_employees_by_dept('Инженер')
WHERE цалин > 2000000;
DEFAULT параметр ба алдаа шидэх
-- Хуучин захиалгыг архивлах функц
CREATE OR REPLACE FUNCTION archive_old_orders(days_old INT DEFAULT 365)
RETURNS INT
LANGUAGE plpgsql
AS $$
DECLARE
moved_count INT;
BEGIN
-- days_old сөрөг байвал алдаа шид
IF days_old <= 0 THEN
RAISE EXCEPTION 'days_old must be positive, got: %', days_old;
END IF;
-- Хуучин захиалгыг тоол
SELECT COUNT(*) INTO moved_count
FROM orders
WHERE created_at < NOW() - (days_old || ' days')::INTERVAL
AND status = 'completed';
-- Тоог буцаах (жишээ — бодит архивлалт хийхгүй)
RETURN moved_count;
END;
$$;
-- Default параметртэй дуудах (365 хоногоос хуучин)
SELECT archive_old_orders();
-- Тусгай утгаар дуудах
SELECT archive_old_orders(90);
Функц устгах
-- Нэр болон параметрийн төрлийг зааж устгана
DROP FUNCTION get_level(INT);
DROP FUNCTION IF EXISTS get_employees_by_dept(TEXT);
Нэг нэртэй олон функц өөр параметртэй байж болох учраас (overloading) устгахдаа параметрийн төрлийг заах шаардлагатай.
Дараагийн хичээлд:
Хүснэгтэд INSERT, UPDATE, DELETE үйлдэл болох үед автоматаар ажилладаг trigger функцийг бичиж сурна.