Trigger үндэс
Өгөгдлийн санд ямар нэгэн үйлдэл болох үед — жишээлбэл шинэ мөр нэмэгдэх, мөр өөрчлөгдөх, устгагдах — автоматаар ажиллах логик бичиж болно. Үүнийг trigger гэнэ. Trigger нь application layer-аас үл хамааран өгөгдлийн санд шууд ажилладаг тул дүрмүүдийг нэг газар нэгтгэж, алдаа гарах эрсдлийг бууруулдаг.
Trigger хэрхэн ажилладаг вэ?
Trigger нь хоёр хэсгээс бүрдэнэ:
- Trigger функц —
RETURNS TRIGGERбуцаадагPL/pgSQLфункц - Trigger тодорхойлолт — хэзээ, ямар үйлдлийн үед функцийг дуудахыг заана
Жишээ болгон дараах хүснэгтүүдийг ашиглая:
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
price NUMERIC NOT NULL,
stock INT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE audit_log (
id SERIAL PRIMARY KEY,
table_name TEXT NOT NULL,
action TEXT NOT NULL,
old_data JSONB,
new_data JSONB,
changed_at TIMESTAMPTZ DEFAULT NOW()
);
BEFORE trigger — үйлдлийн өмнө
BEFORE trigger нь INSERT/UPDATE/DELETE гүйцэтгэгдэхийн өмнө ажиллана. NEW бичлэгийг өөрчилж болдог тул автоматаар утга дүүргэхэд тохиромжтой:
-- updated_at-г автоматаар шинэчлэх trigger функц
CREATE OR REPLACE FUNCTION set_updated_at()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
NEW.updated_at := NOW();
RETURN NEW;
END;
$$;
-- Trigger тодорхойлолт: UPDATE болох бүрт дуудна
CREATE TRIGGER trg_products_updated_at
BEFORE UPDATE ON products
FOR EACH ROW
EXECUTE FUNCTION set_updated_at();
-- Туршиж үзэх
INSERT INTO products (name, price, stock) VALUES ('Утас', 850000, 10);
UPDATE products SET price = 900000 WHERE id = 1;
-- updated_at автоматаар солигдсон
SELECT name, price, updated_at FROM products WHERE id = 1;
NEW бол шинэ утгуудыг агуулсан тусгай хувьсагч. RETURN NEW гэж буцаавал үйлдэл үргэлжилнэ. RETURN NULL гэвэл үйлдлийг цуцална.
AFTER trigger — үйлдлийн дараа
AFTER trigger нь үйлдэл амжилттай дууссаны дараа ажиллана. Audit log бичих, нөөц системд мэдэгдэл илгээх зэрэгт хэрэглэнэ:
-- Өөрчлөлтийн түүх бичдэг trigger функц
CREATE OR REPLACE FUNCTION log_product_changes()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
IF TG_OP = 'INSERT' THEN
INSERT INTO audit_log (table_name, action, new_data)
VALUES ('products', 'INSERT', ROW_TO_JSON(NEW)::JSONB);
ELSIF TG_OP = 'UPDATE' THEN
INSERT INTO audit_log (table_name, action, old_data, new_data)
VALUES ('products', 'UPDATE',
ROW_TO_JSON(OLD)::JSONB,
ROW_TO_JSON(NEW)::JSONB);
ELSIF TG_OP = 'DELETE' THEN
INSERT INTO audit_log (table_name, action, old_data)
VALUES ('products', 'DELETE', ROW_TO_JSON(OLD)::JSONB);
END IF;
RETURN NULL; -- AFTER trigger-д RETURN NULL байж болно
END;
$$;
-- INSERT, UPDATE, DELETE бүгдэнд ажиллуулах
CREATE TRIGGER trg_products_audit
AFTER INSERT OR UPDATE OR DELETE ON products
FOR EACH ROW
EXECUTE FUNCTION log_product_changes();
TG_OP нь одоогийн үйлдлийн нэрийг агуулдаг тусгай хувьсагч ('INSERT', 'UPDATE', 'DELETE'). OLD бол үйлдлийн өмнөх утгуудыг агуулна.
Trigger шалгах ба устгах
-- Бүх trigger-ийг харах
SELECT trigger_name, event_manipulation, event_object_table, action_timing
FROM information_schema.triggers
WHERE trigger_schema = 'public';
-- Trigger идэвхгүй болгох
ALTER TABLE products DISABLE TRIGGER trg_products_audit;
-- Дахин идэвхжүүлэх
ALTER TABLE products ENABLE TRIGGER trg_products_audit;
-- Trigger устгах
DROP TRIGGER trg_products_audit ON products;
-- Trigger функц устгах
DROP FUNCTION log_product_changes();
Trigger нь хэт олон байвал debug хийхэд хэцүү болдог. Зөвхөн үнэхээр шаардлагатай газарт — audit log, автомат тооцоо, хязгаарлалт — ашиглах нь зөв хандлага юм.
Дараагийн хичээлд:
Олон SQL үйлдлийг нэг transaction болгон нэгтгэж, бүгдийг нэгэн зэрэг амжилттай дуусгах эсвэл бүгдийг цуцлах ACID баталгааг сурна.