Normalizatsiya — 1NF, 2NF, 3NF, BCNF

~25 daq · PostgreSQL · Ma'lumotlar Bazasini Loyihalash

Bitta jadvalda hamma narsa saqlangan:

buyurtma_id | mijoz_ism | mijoz_tel      | mahsulot       | kategoriya  | narx
───────────   ──────────   ──────────────   ─────────────   ──────────   ──────
1             Ali           +998901234567   Noutbuk          Elektronika   8M
2             Ali           +998901234567   Telefon          Elektronika   3M
3             Vali          +998909876543   Ko'ylak          Kiyim         150K

Muammolar: Ali ning telefoni o'zgarsa — ikkita qatorni yangilash kerak. Bir qatorni o'chirsak — mijoz ma'lumotini yo'qotamiz. Normalizatsiya bu muammolarni strukturali hal qiladi.


1NF — birinchi normal shakl

Har katakda faqat bitta qiymat — massiv yoki ro'yxat bo'lmasin:

❌ 1NF buzilishi:
mahsulotlar: "Noutbuk, Telefon, Planshet"  — bir katakda ro'yxat

✅ 1NF:
har mahsulot alohida qatorda
-- ❌
CREATE TABLE buyurtmalar (
  id          INT,
  mahsulotlar TEXT  -- "Noutbuk, Telefon"
);

-- ✅
CREATE TABLE buyurtma_elementlari (
  buyurtma_id INT,
  mahsulot    TEXT
);

2NF — ikkinchi normal shakl

1NF + har ustun PRIMARY KEY ga to'liq bog'liq (qisman bog'liqlik yo'q).

Kompozit kalit bo'lganda muammo:

❌ 2NF buzilishi:
(buyurtma_id, mahsulot_id) → PRIMARY KEY
mahsulot_nomi faqat mahsulot_id ga bog'liq — buyurtma_id ga emas!

buyurtma_id | mahsulot_id | mahsulot_nomi | miqdor
──────────────────────────────────────────────────
1             101            Noutbuk         2
2             101            Noutbuk         1   ← nomi takrorlanmoqda

Yechim — mahsulot ma'lumotini alohida jadvalga:

-- ✅ 2NF
CREATE TABLE mahsulotlar (
  id   INT PRIMARY KEY,
  nomi TEXT
);

CREATE TABLE buyurtma_elementlari (
  buyurtma_id INT,
  mahsulot_id INT REFERENCES mahsulotlar(id),
  miqdor      INT,
  PRIMARY KEY (buyurtma_id, mahsulot_id)
);

3NF — uchinchi normal shakl

2NF + tranzitiv bog'liqlik yo'q (A→B→C bo'lmasin, A→C to'g'ridan bo'lsin).

❌ 3NF buzilishi:
mijoz_id → shahar_id → shahar_nomi
mijoz jadvalida shahar_nomi saqlash — tranzitiv

mijoz_id | shahar_id | shahar_nomi
─────────────────────────────────
1          10          Toshkent
2          10          Toshkent   ← takror

Yechim:

-- ✅ 3NF
CREATE TABLE shaharlar (
  id   INT PRIMARY KEY,
  nomi TEXT
);

CREATE TABLE mijozlar (
  id        INT PRIMARY KEY,
  shahar_id INT REFERENCES shaharlar(id)
  -- shahar_nomi yo'q — shaharlar jadvalidan olinadi
);

BCNF — Boyce-Codd Normal Shakl

3NF ning kuchliroq versiyasi. Amalda kamdan-kam kerak — 3NF yetarli.


Normalizatsiyaning afzalliklari va kamchiliklari

Afzalliklari:
  ✅ Takrorlanish yo'q — ma'lumot bir joyda
  ✅ Yangilash oson   — bir joyni o'zgartirish yetarli
  ✅ Ziddiyat yo'q    — bir versiya

Kamchiliklari:
  ❌ Ko'p JOIN        — ma'lumot ko'p jadvalda
  ❌ Ba'zan sekin     — murakkab so'rovlar

Katta tizimlar uchun ko'pincha 3NF yetarli. Hisobot uchun ba'zan denormalizatsiya (keyingi dars) qilinadi.


Xulosa

1NF — har katakda bitta qiymat, takrorlovchi guruhlar yo'q
2NF — 1NF + har ustun butun PRIMARY KEY ga bog'liq
3NF — 2NF + tranzitiv bog'liqlik yo'q (A→B→C emas)

Amaliy qoida:
  3NF — ko'pchilik loyihalar uchun optimal
  Takrorlanish ko'p bo'lsa — normalizatsiya belgisi

Keyingi dars

49-dars: Denormalizatsiya — qachon va nima uchun