8-bo‘lim
Uchinchi normal shakl va BCNF
Tranzitiv bog'liqlik, 3NF ga keltirish, BCNF va uning 3NF dan farqi, normal shakllar xulosasi.
Ushbu bo‘lim mundarijasi
2NF kalitning qismiga bog'liqlikni yo'q qildi. 3NF esa kalitga umuman bog'liq bo'lmagan bog'liqliklarni oladi.
Tranzitiv bog'liqlik #
3NF buzilgan jadval #
CREATE TABLE xodimlar_yomon (
id INT PRIMARY KEY,
ism VARCHAR(100) NOT NULL,
bolim_id INT NOT NULL,
bolim_nomi VARCHAR(50) NOT NULL,
bolim_boshligi VARCHAR(100) NOT NULL,
bolim_qavati TINYINT NOT NULL
);
INSERT INTO xodimlar_yomon VALUES
(1, 'Husanboy', 10, 'IT', 'Nodira Karimova', 3),
(2, 'Malika', 20, 'Hisobot', 'Aziza Tosheva', 2),
(3, 'Kamola', 10, 'IT', 'Nodira Karimova', 3),
(4, 'Dilnoza', 10, 'IT', 'Nodira Karimova', 3);
SELECT id, ism, bolim_nomi, bolim_boshligi
FROM xodimlar_yomon
ORDER BY id;
+----+----------+------------+-----------------+
| id | ism | bolim_nomi | bolim_boshligi |
+----+----------+------------+-----------------+
| 1 | Husanboy | IT | Nodira Karimova |
| 2 | Malika | Hisobot | Aziza Tosheva |
| 3 | Kamola | IT | Nodira Karimova |
| 4 | Dilnoza | IT | Nodira Karimova |
+----+----------+------------+-----------------+
Bu jadval 2NF da - kalit bitta ustun (id), shuning uchun
qisman bog'liqlik mumkin emas.
Lekin muammo bor: Nodira Karimova uch marta takrorlangan.
Bog'liqlikni aniqlash #
-- bolim_id -> bolim_nomi bog'liqligi bormi?
SELECT bolim_id,
COUNT(DISTINCT bolim_nomi) AS turli_nom,
COUNT(DISTINCT bolim_boshligi) AS turli_boshliq,
COUNT(*) AS qatorlar
FROM xodimlar_yomon
GROUP BY bolim_id
ORDER BY bolim_id;
+----------+-----------+---------------+----------+
| bolim_id | turli_nom | turli_boshliq | qatorlar |
+----------+-----------+---------------+----------+
| 10 | 1 | 1 | 3 |
| 20 | 1 | 1 | 1 |
+----------+-----------+---------------+----------+
bolim_id bir xil bo'lganda bolim_nomi va bolim_boshligi
har doim bir xil. Demak bog'liqlik zanjiri shunday:
id -> bolim_id -> bolim_nomi, bolim_boshligi, bolim_qavati
Jadval 3NF da bo'ladi, agar u 2NF da bo'lsa va hech bir kalitga kirmaydigan ustun boshqa kalitga kirmaydigan ustunga bog'liq bo'lmasa.
Qisqacha eslab qolish uchun klassik ibora:
Har bir kalit emas ustun kalitga, butun kalitga va faqat kalitga bog'liq bo'lishi kerak.
| Qism | Qaysi normal shakl |
|---|---|
| "kalitga" | 1NF |
| "butun kalitga" | 2NF |
| "faqat kalitga" | 3NF |
bolim_boshligi xodim_id ga emas, bolim_id ga bog'liq -
ya'ni "faqat kalitga" sharti buzilgan.
Anomaliyalar #
-- 1. Bo'lim boshlig'i almashdi - uch qatorni yangilash kerak
UPDATE xodimlar_yomon
SET bolim_boshligi = 'Malika Yusupova'
WHERE id = 1;
SELECT bolim_id, COUNT(DISTINCT bolim_boshligi) AS turli_boshliq
FROM xodimlar_yomon
WHERE bolim_id = 10
GROUP BY bolim_id;
+----------+---------------+
| bolim_id | turli_boshliq |
+----------+---------------+
| 10 | 2 |
+----------+---------------+
-- 2. Xodimsiz bo'lim saqlanmaydi
DELETE FROM xodimlar_yomon WHERE bolim_id = 20;
SELECT COUNT(*) AS hisobot_bolimi_haqida
FROM xodimlar_yomon
WHERE bolim_nomi = 'Hisobot';
+-----------------------+
| hisobot_bolimi_haqida |
+-----------------------+
| 0 |
+-----------------------+
3NF ga keltirish #
CREATE TABLE bolimlar (
id INT PRIMARY KEY,
nom VARCHAR(50) NOT NULL UNIQUE,
boshliq VARCHAR(100) NOT NULL,
qavat TINYINT NOT NULL
);
CREATE TABLE xodimlar (
id INT PRIMARY KEY,
ism VARCHAR(100) NOT NULL,
bolim_id INT NOT NULL,
FOREIGN KEY (bolim_id) REFERENCES bolimlar(id)
);
INSERT INTO bolimlar VALUES
(10, 'IT', 'Nodira Karimova', 3),
(20, 'Hisobot', 'Aziza Tosheva', 2),
(30, 'Marketing', 'Dilnoza Yusupova', 1);
INSERT INTO xodimlar VALUES
(1, 'Husanboy', 10),
(2, 'Malika', 20),
(3, 'Kamola', 10),
(4, 'Dilnoza', 10);
SELECT x.ism, b.nom AS bolim, b.boshliq
FROM xodimlar x
JOIN bolimlar b ON b.id = x.bolim_id
ORDER BY x.id;
+----------+---------+-----------------+
| ism | bolim | boshliq |
+----------+---------+-----------------+
| Husanboy | IT | Nodira Karimova |
| Malika | Hisobot | Aziza Tosheva |
| Kamola | IT | Nodira Karimova |
| Dilnoza | IT | Nodira Karimova |
+----------+---------+-----------------+
Anomaliyalar yo'qoldi #
-- 1. Boshliq almashdi - BITTA qator
UPDATE bolimlar SET boshliq = 'Malika Yusupova' WHERE id = 10;
SELECT x.ism, b.boshliq
FROM xodimlar x
JOIN bolimlar b ON b.id = x.bolim_id
WHERE b.id = 10
ORDER BY x.id;
+----------+-----------------+
| ism | boshliq |
+----------+-----------------+
| Husanboy | Malika Yusupova |
| Kamola | Malika Yusupova |
| Dilnoza | Malika Yusupova |
+----------+-----------------+
-- 2. Xodimsiz bo'lim ham saqlanadi
SELECT b.nom, COUNT(x.id) AS xodimlar_soni
FROM bolimlar b
LEFT JOIN xodimlar x ON x.bolim_id = b.id
GROUP BY b.id, b.nom
ORDER BY b.id;
+-----------+---------------+
| nom | xodimlar_soni |
+-----------+---------------+
| IT | 3 |
| Hisobot | 1 |
| Marketing | 0 |
+-----------+---------------+
Marketing bo'limi hali xodimsiz, lekin mavjud.
Amalda 3NF buzilishini quyidagi belgilar bilan topasiz:
| Belgi | Misol |
|---|---|
| Ustunlar umumiy prefiks bilan | bolim_nomi, bolim_boshligi |
_id ustuni yonida uning tafsilotlari | bolim_id + bolim_nomi |
| Ma'lumot guruh-guruh takrorlanadi | Uch qatorda bir xil uchlik |
| "Bu ustun kim haqida?" savoliga boshqa javob | Xodim emas, bo'lim haqida |
Eng oddiy tekshiruv - ustun nomlarini o'qing. Agar jadval
xodimlar deb atalgan bo'lsa, lekin ustunlar bolim_ bilan
boshlansa - ular boshqa jadvalga tegishli.
Yana bir klassik misol:
buyurtmalar (id, mijoz_id, mijoz_shahri, yetkazish_narxi)
yetkazish_narxi mijoz_shahri ga bog'liq bo'lsa - bu ham
tranzitiv bog'liqlik. Narxlar alohida shaharlar jadvaliga
chiqadi.
BCNF - 3NF dan kuchliroq #
Klassik misol: har fanni bir o'qituvchi o'qitadi, lekin bir o'qituvchi bir necha fan o'qitishi mumkin.
CREATE TABLE dars_biriktirish (
talaba_id INT NOT NULL,
fan VARCHAR(50) NOT NULL,
oqituvchi VARCHAR(100) NOT NULL,
PRIMARY KEY (talaba_id, fan)
);
INSERT INTO dars_biriktirish VALUES
(1, 'Matematika', 'Nodira Karimova'),
(1, 'Fizika', 'Aziza Tosheva'),
(2, 'Matematika', 'Nodira Karimova'),
(3, 'Matematika', 'Nodira Karimova');
SELECT talaba_id, fan, oqituvchi
FROM dars_biriktirish
ORDER BY talaba_id, fan;
+-----------+------------+-----------------+
| talaba_id | fan | oqituvchi |
+-----------+------------+-----------------+
| 1 | Fizika | Aziza Tosheva |
| 1 | Matematika | Nodira Karimova |
| 2 | Matematika | Nodira Karimova |
| 3 | Matematika | Nodira Karimova |
+-----------+------------+-----------------+
-- fan -> oqituvchi bog'liqligi bor
SELECT fan, COUNT(DISTINCT oqituvchi) AS turli_oqituvchi
FROM dars_biriktirish
GROUP BY fan
ORDER BY fan;
+------------+-----------------+
| fan | turli_oqituvchi |
+------------+-----------------+
| Fizika | 1 |
| Matematika | 1 |
+------------+-----------------+
Tekshiramiz:
- 1NF: har katakda bitta qiymat - ha;
- 2NF:
oqituvchi(talaba_id, fan)juftligiga bog'liqmi? Aslida faqatfanga bog'liq - qisman bog'liqlik!
To'xtang - demak bu 2NF ni ham buzadi?
Bu yerda nozik jihat bor. oqituvchi kalitga kiruvchi
atribut hisoblanadimi? (fan, oqituvchi) ham nomzod kalit
bo'lishi mumkin (agar talaba bir fanni bir o'qituvchidan
o'qisa). Bunday holatda oqituvchi asosiy atribut bo'lib
qoladi va 2NF/3NF ta'riflari unga qo'llanmaydi.
BCNF esa qat'iyroq:
Har bir funksional bog'liqlik
X → Yda X super kalit bo'lishi kerak.
Bu yerda fan → oqituvchi bor, lekin fan super kalit
emas (u yolg'iz qatorni aniqlamaydi). Demak BCNF buzilgan.
Yechim - jadvalni ikkiga bo'lish:
fan_oqituvchi (fan PK, oqituvchi)
talaba_fan (talaba_id, fan) PK (talaba_id, fan)
BCNF ga keltirish #
CREATE TABLE fan_oqituvchi (
fan VARCHAR(50) PRIMARY KEY,
oqituvchi VARCHAR(100) NOT NULL
);
CREATE TABLE talaba_fan (
talaba_id INT NOT NULL,
fan VARCHAR(50) NOT NULL,
PRIMARY KEY (talaba_id, fan),
FOREIGN KEY (fan) REFERENCES fan_oqituvchi(fan)
);
INSERT INTO fan_oqituvchi VALUES
('Matematika', 'Nodira Karimova'),
('Fizika', 'Aziza Tosheva');
INSERT INTO talaba_fan VALUES
(1, 'Matematika'), (1, 'Fizika'),
(2, 'Matematika'), (3, 'Matematika');
SELECT tf.talaba_id, tf.fan, fo.oqituvchi
FROM talaba_fan tf
JOIN fan_oqituvchi fo ON fo.fan = tf.fan
ORDER BY tf.talaba_id, tf.fan;
+-----------+------------+-----------------+
| talaba_id | fan | oqituvchi |
+-----------+------------+-----------------+
| 1 | Fizika | Aziza Tosheva |
| 1 | Matematika | Nodira Karimova |
| 2 | Matematika | Nodira Karimova |
| 3 | Matematika | Nodira Karimova |
+-----------+------------+-----------------+
-- Endi o'qituvchini almashtirish - bitta qator
UPDATE fan_oqituvchi SET oqituvchi = 'Kamola Rasulova' WHERE fan = 'Matematika';
SELECT fan, oqituvchi FROM fan_oqituvchi ORDER BY fan;
+------------+-----------------+
| fan | oqituvchi |
+------------+-----------------+
| Fizika | Aziza Tosheva |
| Matematika | Kamola Rasulova |
+------------+-----------------+
Normal shakllar xulosasi #
| Normal shakl | Nimani yo'q qiladi |
|---|---|
| 1NF | Ko'p qiymatli va takrorlanuvchi ustunlar |
| 2NF | Kalitning qismiga qisman bog'liqlik |
| 3NF | Kalitga kirmaydigan ustunlar orasidagi bog'liqlik |
| BCNF | Har qanday super kalit bo'lmagan aniqlovchi |
| 4NF, 5NF | Ko'p qiymatli va birlashma bog'liqliklari |
3NF - amaliy standart. Ko'p loyiha uchun yetarli.
BCNF kerak bo'ladigan holat juda kam: jadvalda bir necha ustunli, kesishuvchi nomzod kalitlar bo'lganda. Odatiy sxemalarda bunday holat deyarli uchramaydi.
4NF va 5NF esa asosan nazariy - ular mustaqil ko'p qiymatli bog'liqliklarni ko'rib chiqadi. Amaliyotda ularni bilib, lekin qo'llamay ketaverasiz.
Amaliy tartib:
- Sxemani 3NF ga keltiring;
- Ishga tushiring va o'lchang;
- Sekin joylarni topsangiz - ongli ravishda denormallang (9-bo'lim).
Boshidan denormallash - erta optimallashtirish. Avval to'g'ri qiling, keyin tez qiling.
- Tranzitiv bog'liqlikli jadval yaratib, ma'lumot kiriting.
COUNT(DISTINCT)bilanbolim_id -> bolim_nomini isbotlang.- Bo'lim boshlig'ini bir joyda o'zgartirib, ziddiyat hosil qiling.
- Bo'limning barcha xodimini o'chirib, ma'lumot yo'qolishini ko'ring.
- Jadvalni ikkiga bo'lib, 3NF ga keltiring.
- Xodimsiz bo'lim saqlanishini tekshiring.
- "Kalitga, butun kalitga, faqat kalitga" iborasini tushuntiring.
- BCNF va 3NF farqini o'z so'zingiz bilan ayting.
fan -> oqituvchibog'liqligini ajratib chiqaring.- Amalda qaysi normal shaklda to'xtash kerakligini asoslang.
Xulosa #
- Tranzitiv bog'liqlik: kalit emas ustun boshqa kalit emas ustunni aniqlaydi.
- 3NF: har ustun faqat kalitga bog'liq bo'lsin.
- Eslab qolish: "kalitga, butun kalitga, faqat kalitga".
- Belgi: ustunlar umumiy prefiks bilan (
bolim_nomi,bolim_boshligi). _idustuni yonida uning tafsilotlari turmasin.- BCNF: har bog'liqlikning chap tomoni super kalit bo'lsin.
- BCNF faqat kesishuvchi nomzod kalitlarda kerak bo'ladi.
- Amalda 3NF yetarli - 4NF va 5NF asosan nazariy.
- Avval to'g'ri qiling, keyin o'lchab optimallashtiring.
Keyingi bo'limda qoidani ataylab buzishni - denormalizatsiyani ko'ramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.