Generated Columns va Computed Values
Muammodan boshlaylik
Mahsulotlar jadvalida narx va miqdor ustunlari bor. Har bir buyurtmaning umumiy qiymati — narx × miqdor. Siz bu hisoblashni har safar qo'lda qilasiz:
SELECT nomi, narx * miqdor AS jami FROM mahsulotlar;
Yoki ilovaning o'zida hisoblaysiz, keyin bazaga yozasiz. Lekin bir muammo bor: narx o'zgarsa — saqlab qo'yilgan jami eskirib qoladi. Bazada narx = 500, ilovada hisoblangan jami = 5000 — lekin narx 600 ga o'zgargan edi. Ma'lumot mos emas.
Bunday holatda Generated Column kerak: baza o'zi hisoblaydi, o'zi yangilab turadi — siz hech narsa qilmaysiz.
Generated Column nima?
Generated Column — qiymati boshqa ustunlar asosida avtomatik hisoblanadigan ustun. Ma'lumotni qo'lda yozmaysiz — PostgreSQL har safar formulani ishlatadi.
Hayotiy o'xshatma: Excel dagi formula. A katakchaga narx, B katakchaga miqdor yozsangiz — C katakchada =A*B formulasi yozilgan. A yoki B o'zgarsa, C darhol yangilanadi. Siz C ni qo'lda kiritmaganingiz kabi, Generated Column ham qo'lda to'ldirilmaydi — baza o'zi qiladi.
narx │ miqdor │ jami (generated)
──────┼────────┼──────────────────
500 │ 10 │ 5000 ← baza hisobladi
800 │ 5 │ 4000 ← baza hisobladi
300 │ 20 │ 6000 ← baza hisobladi
narx o'zgardi (500 → 600):
600 │ 10 │ 6000 ← baza o'zi yangiladi ✅
Yaratish sintaksisi
CREATE TABLE buyurtma_qatorlari (
id SERIAL PRIMARY KEY,
nomi TEXT NOT NULL,
narx NUMERIC NOT NULL,
miqdor INT NOT NULL,
jami NUMERIC GENERATED ALWAYS AS (narx * miqdor) STORED
-- ↑ formula ↑ diskda saqlash
);
GENERATED ALWAYS AS (formula) STORED — bu kalit so'zlar.
GENERATED ALWAYS — bu ustunni qo'lda o'zgartirib bo'lmaydi, faqat formula ishlaydi.
STORED — hisoblangan qiymat diskda saqlanadi. PostgreSQL da hozircha faqat STORED qo'llab-quvvatlanadi — VIRTUAL (hisoblangan lekin saqlanmagan) hali yo'q.
Amalda qanday ishlaydi
INSERT INTO buyurtma_qatorlari (nomi, narx, miqdor) VALUES
('Noutbuk', 5000000, 2),
('Sichqon', 150000, 5),
('Klaviatura', 350000, 3);
SELECT nomi, narx, miqdor, jami FROM buyurtma_qatorlari;
nomi │ narx │ miqdor │ jami
-------------+-----------+--------+-----------
Noutbuk │ 5 000 000 │ 2 │ 10 000 000
Sichqon │ 150 000 │ 5 │ 750 000
Klaviatura │ 350 000 │ 3 │ 1 050 000
jami ni siz yozmadingiz — PostgreSQL o'zi hisobladi.
Narx yangilansa:
UPDATE buyurtma_qatorlari SET narx = 200000 WHERE nomi = 'Sichqon';
SELECT nomi, narx, jami FROM buyurtma_qatorlari WHERE nomi = 'Sichqon';
nomi │ narx │ jami
---------+---------+---------
Sichqon │ 200 000 │ 1000000 ← avtomatik yangilandi ✅
Ko'proq misollar
Generated column faqat arifmetika emas — har qanday deterministik ifoda bo'lishi mumkin.
Matn birlashtirish
CREATE TABLE foydalanuvchilar (
id SERIAL PRIMARY KEY,
ism TEXT NOT NULL,
familiya TEXT NOT NULL,
toʻliq_ism TEXT GENERATED ALWAYS AS (ism || ' ' || familiya) STORED
);
INSERT INTO foydalanuvchilar (ism, familiya) VALUES ('Ali', 'Karimov');
SELECT toʻliq_ism FROM foydalanuvchilar;
-- Ali Karimov
Katta-kichik harf normallashtirish
Qidiruvda katta-kichik harf muammosini hal qilish uchun:
CREATE TABLE mahsulotlar (
id SERIAL PRIMARY KEY,
nomi TEXT NOT NULL,
nomi_lower TEXT GENERATED ALWAYS AS (LOWER(nomi)) STORED
);
CREATE INDEX ON mahsulotlar (nomi_lower);
-- Endi katta-kichik harfsiz tez qidirish mumkin
SELECT * FROM mahsulotlar
WHERE nomi_lower = LOWER('noutbuk PRO');
LOWER(nomi) ustuniga index qo'yish mumkin emas — lekin generated column ga qo'ysa bo'ladi.
Sana hisoblash
CREATE TABLE shartnomalar (
id SERIAL PRIMARY KEY,
boshlanish DATE NOT NULL,
tugash DATE NOT NULL,
davomiylik INT GENERATED ALWAYS AS (tugash - boshlanish) STORED
-- kun hisobida davomiylik
);
INSERT INTO shartnomalar (boshlanish, tugash)
VALUES ('2024-01-01', '2024-12-31');
SELECT davomiylik FROM shartnomalar;
-- 365
Generated column ga yozib bo'lmaydi
Generated column ni qo'lda o'zgartirishga urinish xato beradi:
-- ❌ — qo'lda yozish mumkin emas
INSERT INTO buyurtma_qatorlari (nomi, narx, miqdor, jami)
VALUES ('Monitor', 2800000, 1, 9999999);
-- ERROR: cannot insert a non-DEFAULT value into column "jami"
-- ❌ — yangilash ham mumkin emas
UPDATE buyurtma_qatorlari SET jami = 9999999 WHERE id = 1;
-- ERROR: column "jami" can only be updated to DEFAULT
Bu xavfsizlik kafolati — formula hamisha to'g'ri natija beradi, qo'lda buzib bo'lmaydi.
Generated column cheklovlari
Generated column formulasida ba'zi narsalar bo'lmaydi:
✅ Ishlaydi:
Boshqa ustunlar → narx * miqdor
Matematik funksiyalar → ROUND(narx * 0.12, 2)
Matn funksiyalari → LOWER(nomi), TRIM(matn)
Sana funksiyalari → tugash - boshlanish
CASE ifodasi → CASE WHEN narx > 1000000 THEN 'qimmat' ELSE 'arzon' END
❌ Ishlamaydi:
Boshqa jadvalga murojaat → (SELECT nomi FROM ...)
Sequence → nextval(...)
O'zgaruvchan funksiyalar → now(), random()
Boshqa generated column → boshqa_generated * 2
Nima uchun now() ishlamaydi? now() har safar boshqa qiymat qaytaradi — generated column esa deterministik bo'lishi kerak, ya'ni kirish qiymatlari bir xil bo'lsa, natija har doim bir xil chiqishi shart.
DEFAULT va Generated Column — farqi
Ikkisi ham ustunni avtomatik to'ldiradi — lekin farqlari bor:
DEFAULT: Generated Column:
──────────────────────────── ────────────────────────────────
Faqat qo'shishda ishlaydi Qo'shish va yangilashda ishlaydi
Qo'lda o'zgartirib bo'ladi Qo'lda o'zgartirib bo'lmaydi
Boshqa ustunlarga bog'liq emas Boshqa ustunlar asosida hisoblanadi
now(), random() ishlaydi Deterministik funksiyalar kerak
-- DEFAULT — bir marta qo'shilganda qiymat beriladi, keyin mustaqil
sana TIMESTAMPTZ DEFAULT now() -- qo'shilganda vaqt yozildi, o'zgarmaydi
-- Generated — har doim formulaga bog'liq
jami NUMERIC GENERATED ALWAYS AS (narx * miqdor) STORED -- narx o'zgarsa, jami ham o'zgaradi
Tez-tez uchraydigan xatolar
Formulada boshqa jadvalga murojaat qilish:
-- ❌ — subquery ishlamaydi
jami NUMERIC GENERATED ALWAYS AS (
(SELECT SUM(narx) FROM boshqa_jadval WHERE ...)
) STORED;
-- ERROR: cannot use subquery in column generation expression
Generated column faqat o'sha qatorning boshqa ustunlari bilan ishlaydi — boshqa jadvalga murojaat imkonsiz.
STORED kalit so'zini unutish:
-- ❌ — STORED yozilmadi
jami NUMERIC GENERATED ALWAYS AS (narx * miqdor);
-- ERROR: generated columns must be stored
-- ✅
jami NUMERIC GENERATED ALWAYS AS (narx * miqdor) STORED;
PostgreSQL da hozircha STORED majburiy — VIRTUAL qo'llab-quvvatlanmaydi.
Xulosa
Generated Column — qiymati boshqa ustunlar asosida avtomatik hisoblanadigan ustun. Excel dagi formula kabi — manba o'zgarsa, natija o'zgaradi.
GENERATED ALWAYS AS (formula) STORED
Qachon kerak:
- Hisoblangan qiymatni tez-tez o'qish kerak, lekin har safar hisoblash qimmat
- Index qo'yish kerak bo'lgan hisoblangan ustun (
LOWER(nomi),narx * miqdor) - Ma'lumot izchilligini kafolatlash — qo'lda xato kiritishdan himoya
Cheklov: Deterministik bo'lishi shart, subquery yo'q, now() va random() yo'q, boshqa generated column ga bog'liq bo'lmaydi.
Keyingi dars
30-dars: Built-in funksiyalar — string, number, date, conditional