99 / 100

BEFORE INSERT TRIGGER

Qo'shishdan oldingi trigirlar

Ushbu qo'llanmada PostgreSQLda jadvalga yangi qator kiritilishidan oldin ma'lumotlarni tekshirish va biznes qoidalarini majburlash uchun BEFORE INSERT trigirlaridan qanday foydalanishni o'rganasiz.

BEFORE INSERT trigirlariga kirish

BEFORE INSERT trigiri jadvalga INSERT amali orqali yangi qator qo'shilishi arafasida — ya'ni ma'lumotlar diskka yozilishidan oldin ishga tushadi.

BEFORE INSERT trigirlari odatda quyidagi maqsadlarda ishlatiladi:

  1. Ma'lumotlarni tekshirish (Validation): Kiritilayotgan ma'lumotlar mavjud boshqa jadvallardagi cheklovlarga yoki murakkab shartlarga javob berishini tekshirish.
  2. Xatolik berish va kiritishni to'xtatish: Agar shart bajarilmasa, RAISE EXCEPTION orqali amaliyotni butunlay to'xtatish.
  3. Ma'lumotlarni to'g'rilash (Transformation): NEW.column_name qiymatlarini avtomatik o'zgartirish (masalan, bo'sh joylarni tozalash, katta harfga o'tkazish).

Sintaksisi:

query.sql
CREATE TRIGGER trigger_name
BEFORE INSERT
ON table_name
FOR EACH { ROW | STATEMENT }
EXECUTE FUNCTION trigger_function();

[!IMPORTANT] Qator darajasidagi (FOR EACH ROW) BEFORE INSERT trigir funksiyasi oxirida har doim RETURN NEW; qaytarishi kerak. Agar funksiya RETURN NULL; qaytarsa, qator jadvalga umuman qo'shilmaydi.

Namunaviy jadvallar

Misol uchun, ombordagi tovarlar qoldig'ini nazorat qiluvchi tizimni ko'rib chiqamiz:

query.sql
DROP TABLE IF EXISTS transactions CASCADE;
DROP TABLE IF EXISTS inventories CASCADE;

CREATE TABLE inventories (
    inventory_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    product_id INT NOT NULL,
    warehouse_id INT NOT NULL,
    quantity INT NOT NULL,
    UNIQUE (product_id, warehouse_id)
);

CREATE TABLE transactions (
    transaction_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    product_id INT NOT NULL,
    warehouse_id INT NOT NULL,
    user_id INT NOT NULL,
    type VARCHAR(20) NOT NULL,
    quantity INT NOT NULL,
    transaction_date DATE NOT NULL
);

INSERT INTO inventories (product_id, warehouse_id, quantity)
VALUES (2, 2, 150);

Hozirda 2-omborimizda 2-raqamli mahsulotdan 150 dona bor.

BEFORE INSERT amaliy misoli

Aytaylik, kimdir ombordan tovar chiqarish (type = 'issue') bo'yicha tranzaksiya kiritmoqchi bo'lsa, avval ombordagi joriy qoldiq yetarli ekanini tekshirishimiz kerak. Agar tovar yetarli bo'lmasa, tranzaksiya kiritilishiga yo'l qo'ymasligimiz zarur.

1) Tekshiruvchi trigir funksiyasini yaratish

query.sql
CREATE OR REPLACE FUNCTION validate_inventory()
RETURNS TRIGGER 
AS $$
DECLARE
    v_quantity INT;
BEGIN
    -- Ombordagi joriy qoldiqni olamiz
    SELECT quantity INTO v_quantity
    FROM inventories
    WHERE product_id = NEW.product_id 
      AND warehouse_id = NEW.warehouse_id;

    -- Agar tovar chiqarilayotgan bo'lsa, qoldiq yetarliligini tekshiramiz
    IF NEW.type = 'issue' THEN
        IF v_quantity IS NULL OR v_quantity < NEW.quantity THEN
            RAISE EXCEPTION 'Omborda yetarli tovar mavjud emas! (mahsulot: %, ombor: %, mavjud qoldiq: %, so''ralgan: %)', 
                            NEW.product_id, NEW.warehouse_id, COALESCE(v_quantity, 0), NEW.quantity;
        END IF;
    END IF;

    RETURN NEW;
END;
$$ 
LANGUAGE plpgsql;

2) BEFORE INSERT trigirini yaratish

query.sql
CREATE TRIGGER before_insert_transaction
BEFORE INSERT ON transactions
FOR EACH ROW
EXECUTE FUNCTION validate_inventory();

3) Trigirni sinab ko'rish

Omborda 150 dona bor. Endi 200 dona chiqarishga harakat qilib ko'ramiz:

query.sql
INSERT INTO transactions (product_id, warehouse_id, user_id, type, quantity, transaction_date)
VALUES (2, 2, 1, 'issue', 200, '2026-09-22');

PostgreSQL qat'iy xatolik beradi va qatorni kiritishni to'xtatadi:

matn
ERROR:  Omborda yetarli tovar mavjud emas! (mahsulot: 2, ombor: 2, mavjud qoldiq: 150, so'ralgan: 200)
CONTEXT:  PL/pgSQL function validate_inventory() line 14 at RAISE

Endi yetarli miqdor (masalan, 20 dona) bilan urinib ko'ramiz:

query.sql
INSERT INTO transactions (product_id, warehouse_id, user_id, type, quantity, transaction_date)
VALUES (2, 2, 1, 'issue', 20, '2026-09-22');

Natija: so'rov xatosiz muvaffaqiyatli bajariladi va transactions jadvaliga yangi qator yoziladi.

Xulosa

  • BEFORE INSERT trigirlari yangi qator bazaga saqlanishidan oldin ma'lumotlarni tekshirish uchun ideal vositadir.
  • NEW o'zgaruvchisi orqali qo'shilayotgan qator maydonlariga murojaat qilinadi.
  • Qoida buzilganda RAISE EXCEPTION yordamida jarayon bekor qilinadi.
  • Funksiya oxirida qator qo'shilishiga ruxsat berish uchun RETURN NEW; yozilishi shart.