7-bo‘lim
Ikkinchi normal shakl (2NF)
Funksional bog'liqlik, kompozit kalitga qisman bog'liqlik, 2NF buzilishini aniqlash va jadvalni bo'lish.
Ushbu bo‘lim mundarijasi
1NF bajarilgach, keyingi savol tug'iladi: har bir ustun butun kalitga bog'liqmi, yoki uning bir qismiga?
Funksional bog'liqlik #
2NF buzilgan jadval #
CREATE TABLE yozilishlar_yomon (
talaba_id INT NOT NULL,
fan_id INT NOT NULL,
talaba_ismi VARCHAR(100) NOT NULL,
talaba_sinfi VARCHAR(10) NOT NULL,
fan_nomi VARCHAR(50) NOT NULL,
fan_krediti TINYINT NOT NULL,
baho TINYINT,
PRIMARY KEY (talaba_id, fan_id)
);
INSERT INTO yozilishlar_yomon VALUES
(1, 1, 'Husanboy', '9-A', 'Matematika', 6, 5),
(1, 2, 'Husanboy', '9-A', 'Fizika', 4, 4),
(1, 3, 'Husanboy', '9-A', 'Ingliz tili', 3, 5),
(2, 1, 'Malika', '9-A', 'Matematika', 6, 4),
(2, 2, 'Malika', '9-A', 'Fizika', 4, 5),
(3, 1, 'Kamola', '9-B', 'Matematika', 6, 3);
SELECT talaba_id, fan_id, talaba_ismi, fan_nomi, baho
FROM yozilishlar_yomon
ORDER BY talaba_id, fan_id;
+-----------+--------+-------------+-------------+------+
| talaba_id | fan_id | talaba_ismi | fan_nomi | baho |
+-----------+--------+-------------+-------------+------+
| 1 | 1 | Husanboy | Matematika | 5 |
| 1 | 2 | Husanboy | Fizika | 4 |
| 1 | 3 | Husanboy | Ingliz tili | 5 |
| 2 | 1 | Malika | Matematika | 4 |
| 2 | 2 | Malika | Fizika | 5 |
| 3 | 1 | Kamola | Matematika | 3 |
+-----------+--------+-------------+-------------+------+
Jadval 1NF da - har katakda bitta qiymat. Lekin muammo ko'rinib
turibdi: Husanboy uch marta, Matematika uch marta takrorlangan.
Qisman bog'liqlikni aniqlash #
Birlamchi kalit - (talaba_id, fan_id). Har ustun uchun savol
beramiz: kalitning qaysi qismiga bog'liq?
| Ustun | Nimaga bog'liq | Holat |
|---|---|---|
talaba_ismi | Faqat talaba_id | Qisman |
talaba_sinfi | Faqat talaba_id | Qisman |
fan_nomi | Faqat fan_id | Qisman |
fan_krediti | Faqat fan_id | Qisman |
baho | Ikkalasiga | To'liq |
-- Isbot: bir xil talaba_id da ism DOIM bir xil
SELECT talaba_id, COUNT(DISTINCT talaba_ismi) AS turli_ismlar
FROM yozilishlar_yomon
GROUP BY talaba_id
ORDER BY talaba_id;
+-----------+--------------+
| talaba_id | turli_ismlar |
+-----------+--------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
+-----------+--------------+
-- Baho esa faqat juftlikka bog'liq - bir talabada turli baholar bor
SELECT talaba_id, COUNT(DISTINCT baho) AS turli_baholar
FROM yozilishlar_yomon
GROUP BY talaba_id
ORDER BY talaba_id;
+-----------+---------------+
| talaba_id | turli_baholar |
+-----------+---------------+
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
+-----------+---------------+
Jadval 2NF da bo'ladi, agar u 1NF da bo'lsa va har bir kalitga kirmaydigan ustun butun birlamchi kalitga to'liq bog'liq bo'lsa.
Boshqacha aytganda: kalitning bir qismi yetarli bo'lgan ustun bo'lmasligi kerak.
Muhim natija: agar birlamchi kalit bitta ustundan iborat bo'lsa, jadval avtomatik 2NF da bo'ladi - qisman bog'liqlik jismonan mumkin emas.
Shuning uchun 2NF muammosi faqat kompozit kalitli jadvallarda
uchraydi. Sun'iy id ishlatilganda bu muammo ko'pincha
o'z-o'zidan yo'qoladi - lekin yashiringan holda qolishi ham
mumkin (quyidagi ogohlantirishga qarang).
Anomaliyalar #
-- 1. Yangilash anomaliyasi: ismni bir joyda o'zgartirdik
UPDATE yozilishlar_yomon
SET talaba_ismi = 'Husanboy Qodirov'
WHERE talaba_id = 1 AND fan_id = 1;
SELECT talaba_id, COUNT(DISTINCT talaba_ismi) AS turli_ismlar
FROM yozilishlar_yomon
WHERE talaba_id = 1
GROUP BY talaba_id;
+-----------+--------------+
| talaba_id | turli_ismlar |
+-----------+--------------+
| 1 | 2 |
+-----------+--------------+
-- 2. O'chirish anomaliyasi: Kamolaning yagona bahosini o'chirsak,
-- uning ismi va sinfi ham yo'qoladi
DELETE FROM yozilishlar_yomon WHERE talaba_id = 3;
SELECT COUNT(*) AS kamola_haqida_malumot
FROM yozilishlar_yomon
WHERE talaba_ismi = 'Kamola';
+-----------------------+
| kamola_haqida_malumot |
+-----------------------+
| 0 |
+-----------------------+
-- 3. Qo'shish anomaliyasi: hali hech kim yozilmagan fanni
-- qo'shib bo'lmaydi - talaba_id kerak
INSERT INTO yozilishlar_yomon (fan_id, fan_nomi, fan_krediti)
VALUES (4, 'Tarix', 2);
ERROR 1364 (HY000): Field 'talaba_id' doesn't have a default value
2NF ga keltirish #
CREATE TABLE talabalar (
id INT PRIMARY KEY AUTO_INCREMENT,
ism VARCHAR(100) NOT NULL,
sinf VARCHAR(10) NOT NULL
);
CREATE TABLE fanlar (
id INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(50) NOT NULL UNIQUE,
kredit TINYINT NOT NULL
);
CREATE TABLE yozilishlar (
talaba_id INT NOT NULL,
fan_id INT NOT NULL,
baho TINYINT,
PRIMARY KEY (talaba_id, fan_id),
FOREIGN KEY (talaba_id) REFERENCES talabalar(id),
FOREIGN KEY (fan_id) REFERENCES fanlar(id)
);
INSERT INTO talabalar (ism, sinf) VALUES
('Husanboy', '9-A'), ('Malika', '9-A'), ('Kamola', '9-B');
INSERT INTO fanlar (nom, kredit) VALUES
('Matematika', 6), ('Fizika', 4), ('Ingliz tili', 3);
INSERT INTO yozilishlar VALUES
(1, 1, 5), (1, 2, 4), (1, 3, 5),
(2, 1, 4), (2, 2, 5),
(3, 1, 3);
Xuddi shu ma'lumot, endi uch jadvalda:
SELECT t.ism, f.nom AS fan, y.baho
FROM yozilishlar y
JOIN talabalar t ON t.id = y.talaba_id
JOIN fanlar f ON f.id = y.fan_id
ORDER BY y.talaba_id, y.fan_id;
+----------+-------------+------+
| ism | fan | baho |
+----------+-------------+------+
| Husanboy | Matematika | 5 |
| Husanboy | Fizika | 4 |
| Husanboy | Ingliz tili | 5 |
| Malika | Matematika | 4 |
| Malika | Fizika | 5 |
| Kamola | Matematika | 3 |
+----------+-------------+------+
Anomaliyalar yo'qoldi #
-- 1. Ismni o'zgartirish - bitta qator, ziddiyat mumkin emas
UPDATE talabalar SET ism = 'Husanboy Qodirov' WHERE id = 1;
SELECT ism FROM talabalar WHERE id = 1;
+------------------+
| ism |
+------------------+
| Husanboy Qodirov |
+------------------+
-- 2. Barcha bahoni o'chirsak ham talaba qoladi
DELETE FROM yozilishlar WHERE talaba_id = 3;
SELECT ism, sinf FROM talabalar WHERE id = 3;
+--------+------+
| ism | sinf |
+--------+------+
| Kamola | 9-B |
+--------+------+
-- 3. Hali hech kim yozilmagan fanni qo'shish mumkin
INSERT INTO fanlar (nom, kredit) VALUES ('Tarix', 2);
SELECT f.nom, COUNT(y.talaba_id) AS yozilganlar
FROM fanlar f
LEFT JOIN yozilishlar y ON y.fan_id = f.id
GROUP BY f.id, f.nom
ORDER BY f.id;
+-------------+-------------+
| nom | yozilganlar |
+-------------+-------------+
| Matematika | 3 |
| Fizika | 2 |
| Ingliz tili | 1 |
| Tarix | 0 |
+-------------+-------------+
Uchala anomaliya ham yo'qoldi.
id 2NF muammosini yashiradiKo'p dasturchi bog'lovchi jadvalga sun'iy kalit qo'yadi:
CREATE TABLE yozilishlar_yashirin (
id INT PRIMARY KEY AUTO_INCREMENT, -- sun'iy kalit
talaba_id INT NOT NULL,
fan_id INT NOT NULL,
talaba_ismi VARCHAR(100), -- hali ham takrorlanadi!
fan_nomi VARCHAR(50), -- bu ham
baho TINYINT
);
Rasmiy jihatdan bu jadval 2NF da - birlamchi kalit bitta ustun, shuning uchun qisman bog'liqlik "yo'q".
Lekin muammo qolgan: talaba_ismi hamon takrorlanadi va
yangilash anomaliyasi hamon mumkin.
Normal shakllar matematik ta'riflar - ular sxemani mexanik tekshiradi. Ular sog'lom fikrni almashtirmaydi.
To'g'ri savol har doim bir xil:
Bu ustun shu jadvalning mavzusiga tegishlimi?
yozilishlar jadvalining mavzusi - yozilish. Talabaning
ismi unga tegishli emas, u talabaga tegishli.
Shuning uchun UNIQUE (talaba_id, fan_id) qo'yib, mantiqiy
kalitni tiklang - shunda normal shakllar yana ish beradi.
Amaliy tekshirish usuli #
-- Takrorlanish darajasini o'lchash
SELECT
COUNT(*) AS qatorlar,
COUNT(DISTINCT talaba_id) AS noyob_talaba,
COUNT(DISTINCT fan_id) AS noyob_fan
FROM yozilishlar;
+----------+--------------+-----------+
| qatorlar | noyob_talaba | noyob_fan |
+----------+--------------+-----------+
| 6 | 3 | 3 |
+----------+--------------+-----------+
Kompozit kalitli jadvalni ko'rganingizda, har kalitga kirmaydigan ustun uchun so'rang:
"Bu qiymat kalitning bir qismi bilan aniqlanadimi?"
Amaliy belgilar:
| Belgi | Misol |
|---|---|
| Ustun nomida boshqa jadval nomi | talaba_ismi, fan_nomi |
| Bir ustunni bilsangiz, boshqasini bilasiz | fan_id → fan_nomi |
COUNT(DISTINCT) 1 ga teng | Yuqoridagi tekshiruv |
SQL bilan tekshirish:
SELECT talaba_id
FROM yozilishlar_yomon
GROUP BY talaba_id
HAVING COUNT(DISTINCT talaba_ismi) > 1;
Natija bo'sh bo'lsa - talaba_id → talaba_ismi bog'liqligi
bor, ya'ni 2NF buzilgan (kalit kompozit bo'lsa).
Diqqat: bu tekshiruv mavjud ma'lumotga asoslanadi. Ma'lumot kam bo'lsa, tasodifan bog'liqlik ko'rinishi mumkin. Yakuniy qaror biznes qoidasi bo'yicha qabul qilinadi.
Qachon bo'lmaslik kerak #
Bitta muhim istisno bor - vaqt bo'yicha o'zgaradigan qiymatlar.
CREATE TABLE buyurtma_qatorlari (
buyurtma_id INT NOT NULL,
mahsulot_id INT NOT NULL,
soni INT NOT NULL,
narx DECIMAL(10,2) NOT NULL, -- ATAYLAB takrorlangan
PRIMARY KEY (buyurtma_id, mahsulot_id)
);
narx mahsulot_id ga bog'liqdek ko'rinadi - ya'ni 2NF
buzilgan.
Lekin bu xato emas: bu sotilgan paytdagi narx. Mahsulot narxi ertaga o'zgarsa, eski buyurtmalar o'zgarmasligi kerak.
mahsulotlar.narx -- BUGUNGI narx
buyurtma_qatorlari.narx -- SOTILGAN paytdagi narx
Bular turli faktlar, shuning uchun takrorlanish emas.
Xuddi shunday misollar:
| Ustun | Nima uchun nusxalanadi |
|---|---|
| Buyurtmadagi narx | Narx o'zgaradi, tarix qoladi |
| Shartnomadagi manzil | Ko'chib ketishi mumkin |
| Hisobotdagi kurs | O'sha kundagi kurs |
Belgi: qiymat "o'sha paytdagi holat" bo'lsa - nusxalash to'g'ri. Bu 9-bo'limdagi denormalizatsiyaning eng asosli turi.
- Kompozit kalitli jadval yaratib, ma'lumot kiriting.
- Har ustun kalitning qaysi qismiga bog'liqligini aniqlang.
COUNT(DISTINCT)bilan bog'liqlikni isbotlang.- Ismni bir joyda o'zgartirib, ziddiyat hosil qiling.
- Yagona qatorni o'chirib, ma'lumot yo'qolishini ko'ring.
- Yozilmagan fanni qo'shishga urinib ko'ring.
- Jadvalni uchga bo'lib, 2NF ga keltiring.
- Uchala anomaliya yo'qolganini tekshiring.
- Sun'iy
idmuammoni qanday yashirishini tushuntiring. - Buyurtmadagi narx nima uchun takrorlanishi kerakligini ayting.
Xulosa #
- Funksional bog'liqlik: A ni bilsangiz, B ni aniq bilasiz.
- 2NF: har ustun butun kalitga bog'liq bo'lishi kerak.
- Muammo faqat kompozit kalitli jadvallarda bo'ladi.
- Bitta ustunli kalitda jadval avtomatik 2NF da.
- Qisman bog'liqlik uchala anomaliyani keltirib chiqaradi.
- Yechim: kalitning har qismiga o'z jadvali.
- Sun'iy
idmuammoni yashiradi, hal qilmaydi. UNIQUE (a, b)bilan mantiqiy kalitni tiklang.- To'g'ri savol: ustun jadvalning mavzusiga tegishlimi?
- Tarixiy qiymat (sotilgan narx) - ataylab nusxalanadi.
Keyingi bo'limda uchinchi normal shakl va BCNF ni 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.