10-bo‘lim
Jadvallar orasidagi bog'lanishlar
Birlamchi va tashqi kalitlar, bir-ko'p, ko'p-ko'p va bir-bir munosabatlari, referensial butunlik.
Ushbu bo‘lim mundarijasi
- Muammo: takrorlanuvchi ma'lumot
- Yechim: alohida jadvallar + kalit
- Kalit turlari
- Bog'lanish turlari
- 1. Bir-ko'p (1:N) - eng keng tarqalgan
- 2. Ko'p-ko'p (N:M) - oraliq jadval bilan
- 3. Bir-bir (1:1) - kamdan-kam
- ON DELETE va ON UPDATE
- Tashqi kalit nimani himoya qiladi?
- Bog'langan ma'lumotni o'qish
- To'liq sxema misoli
- Tashqi kalitlarni ko'rish
- Xulosa
Relatsion bazaning butun kuchi bog'lanishlarda. Bir jadvaldagi qator boshqasidagi qatorga ishora qiladi.
Muammo: takrorlanuvchi ma'lumot #
-- Yomon: hamma narsa bitta jadvalda
CREATE TABLE buyurtmalar (
id INT PRIMARY KEY,
mijoz_ism VARCHAR(120),
mijoz_telefon VARCHAR(20),
mijoz_manzil VARCHAR(255),
mahsulot VARCHAR(160),
narx DECIMAL(12,2)
);
| id | mijoz_ism | mijoz_telefon | mahsulot |
|---|---|---|---|
| 1 | Husanboy Qodirov | +998901234567 | Klaviatura |
| 2 | Husanboy Qodirov | +998901234567 | Sichqoncha |
| 3 | Husanboy Qodirov | +998901234567 | Monitor |
Muammolar:
| Muammo | Izoh |
|---|---|
| Takrorlanish | Bir ma'lumot 3 marta saqlanmoqda |
| Yangilash anomaliyasi | Telefon o'zgarsa - 3 joyda o'zgartirish kerak |
| Nomuvofiqlik | Bir joyda o'zgartirib, boshqasini unutish |
| O'chirish anomaliyasi | Buyurtmani o'chirsak - mijoz haqidagi ma'lumot ham yo'qoladi |
Yechim: alohida jadvallar + kalit #
CREATE TABLE mijozlar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
ism VARCHAR(120) NOT NULL,
telefon VARCHAR(20),
manzil VARCHAR(255)
) ENGINE=InnoDB;
CREATE TABLE buyurtmalar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
mijoz_id INT UNSIGNED NOT NULL,
mahsulot VARCHAR(160) NOT NULL,
narx DECIMAL(12,2) NOT NULL,
FOREIGN KEY (mijoz_id) REFERENCES mijozlar (id)
) ENGINE=InnoDB;
Kalit turlari #
| Kalit | Vazifasi |
|---|---|
| Birlamchi kalit (PK) | Qatorni yagona aniqlaydi |
| Tashqi kalit (FK) | Boshqa jadvaldagi PK ga ishora qiladi |
| Nomzod kalit | PK bo'la oladigan boshqa noyob ustun (email) |
| Tarkibiy kalit | Bir nechta ustundan tashkil topgan |
Bog'lanish turlari #
1. Bir-ko'p (1:N) - eng keng tarqalgan #
Bitta mijozda ko'p buyurtma bo'ladi, lekin har bir buyurtma bitta mijozniki.
CREATE TABLE guruhlar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nomi VARCHAR(20) NOT NULL UNIQUE
) ENGINE=InnoDB;
CREATE TABLE talabalar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
guruh_id INT UNSIGNED NOT NULL,
ism VARCHAR(120) NOT NULL,
CONSTRAINT fk_talaba_guruh
FOREIGN KEY (guruh_id) REFERENCES guruhlar (id)
ON DELETE RESTRICT
ON UPDATE CASCADE
) ENGINE=InnoDB;
Har doim shunday: talabalar.guruh_id → guruhlar.id.
Bitta guruhda ko'p talaba bo'lgani uchun kalit talabalar jadvalida.
Teskarisi bo'lishi mumkin emas: guruhlar jadvalida talaba_id ustuni bo'lsa,
har bir guruhda faqat bitta talaba bo'lardi.
2. Ko'p-ko'p (N:M) - oraliq jadval bilan #
Bitta talaba ko'p fanni o'qiydi, bitta fanni ko'p talaba o'qiydi.
CREATE TABLE fanlar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nomi VARCHAR(120) NOT NULL
) ENGINE=InnoDB;
-- Oraliq (bog'lovchi) jadval
CREATE TABLE talaba_fan (
talaba_id INT UNSIGNED NOT NULL,
fan_id INT UNSIGNED NOT NULL,
baho TINYINT UNSIGNED,
sana DATE,
PRIMARY KEY (talaba_id, fan_id),
FOREIGN KEY (talaba_id) REFERENCES talabalar (id) ON DELETE CASCADE,
FOREIGN KEY (fan_id) REFERENCES fanlar (id) ON DELETE CASCADE
) ENGINE=InnoDB;
-- Foydalanish
INSERT INTO talaba_fan (talaba_id, fan_id, baho, sana) VALUES
(1, 1, 5, '2026-06-15'),
(1, 2, 4, '2026-06-18'),
(2, 1, 3, '2026-06-15');
3. Bir-bir (1:1) - kamdan-kam #
CREATE TABLE foydalanuvchilar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(190) NOT NULL UNIQUE,
parol VARCHAR(255) NOT NULL
) ENGINE=InnoDB;
CREATE TABLE profillar (
foydalanuvchi_id INT UNSIGNED PRIMARY KEY,
tugilgan_sana DATE,
bio TEXT,
avatar VARCHAR(255),
FOREIGN KEY (foydalanuvchi_id)
REFERENCES foydalanuvchilar (id) ON DELETE CASCADE
) ENGINE=InnoDB;
- Kamdan-kam ishlatiladigan katta ustunlarni ajratish (
TEXT,BLOB) - Maxfiy ma'lumotni alohida saqlash (kirish huquqlarini ajratish uchun)
- Ixtiyoriy ma'lumot (har bir foydalanuvchida profil bo'lmasligi mumkin)
Ko'p hollarda 1:1 o'rniga ustunlarni bitta jadvalga qo'shish soddaroq.
ON DELETE va ON UPDATE #
Ota yozuv o'chirilsa yoki o'zgarsa, bola bilan nima bo'ladi?
| Qiymat | Xatti-harakat |
|---|---|
RESTRICT | Bog'liq yozuv bo'lsa o'chirishga ruxsat bermaydi (standart) |
CASCADE | Bog'liq yozuvlar ham o'chiriladi |
SET NULL | Tashqi kalit NULL ga o'rnatiladi |
NO ACTION | RESTRICT bilan bir xil |
-- Guruh o'chsa, talabalar ham o'chsin
FOREIGN KEY (guruh_id) REFERENCES guruhlar (id)
ON DELETE CASCADE
-- Guruh o'chsa, talabalar guruhsiz qolsin
FOREIGN KEY (guruh_id) REFERENCES guruhlar (id)
ON DELETE SET NULL -- ustun NULL ga ruxsat berishi kerak
-- Talabasi bor guruhni o'chirib bo'lmasin
FOREIGN KEY (guruh_id) REFERENCES guruhlar (id)
ON DELETE RESTRICT
CASCADE bilan ehtiyot bo'lingDELETE FROM mijozlar WHERE id = 1;
Agar buyurtmalar da ON DELETE CASCADE bo'lsa, mijozning barcha buyurtmalari
ham o'chib ketadi. Agar buyurtma_elementlari da ham CASCADE bo'lsa - ular ham.
Bitta so'rov zanjir bo'ylab yuzlab yozuvni o'chirishi mumkin.
Xavfsizroq yondashuv: RESTRICT qo'ying va o'chirish tartibini kodda
aniq boshqaring. Yoki umuman yumshoq o'chirish ishlating.
Tashqi kalit nimani himoya qiladi? #
-- Mavjud bo'lmagan guruhga talaba qo'shishga urinish
INSERT INTO talabalar (guruh_id, ism) VALUES (999, 'Test');
ERROR 1452 (23000): Cannot add or update a child row:
a foreign key constraint fails
-- Talabasi bor guruhni o'chirishga urinish (RESTRICT bilan)
DELETE FROM guruhlar WHERE id = 1;
ERROR 1451 (23000): Cannot delete or update a parent row:
a foreign key constraint fails
Tashqi kalit bazaga noto'g'ri ma'lumot kirishiga yo'l qo'ymaydi. Kodda xato bo'lsa ham, baza o'zini himoya qiladi.
Ba'zi dasturchilar tashqi kalitlarni ishlatmaydi ("kodda tekshiramiz"). Bu xato: kod o'zgaradi, dasturchilar almashadi, lekin baza qoladi. Cheklovlarni bazaga qo'ying.
Bog'langan ma'lumotni o'qish #
-- Ichki so'rov bilan (sekin)
SELECT
ism,
(SELECT nomi FROM guruhlar WHERE id = talabalar.guruh_id) AS guruh
FROM talabalar;
-- JOIN bilan (to'g'ri usul - keyingi bo'lim)
SELECT t.ism, g.nomi AS guruh
FROM talabalar t
JOIN guruhlar g ON g.id = t.guruh_id;
To'liq sxema misoli #
CREATE DATABASE IF NOT EXISTS dokon
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE dokon;
CREATE TABLE kategoriyalar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nomi VARCHAR(80) NOT NULL UNIQUE
) ENGINE=InnoDB;
CREATE TABLE mahsulotlar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
kategoriya_id INT UNSIGNED NOT NULL,
nomi VARCHAR(160) NOT NULL,
narx DECIMAL(12,2) NOT NULL,
ombor INT UNSIGNED NOT NULL DEFAULT 0,
CONSTRAINT fk_mahsulot_kategoriya
FOREIGN KEY (kategoriya_id) REFERENCES kategoriyalar (id)
ON DELETE RESTRICT ON UPDATE CASCADE,
KEY idx_kategoriya (kategoriya_id)
) ENGINE=InnoDB;
CREATE TABLE mijozlar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
ism VARCHAR(120) NOT NULL,
email VARCHAR(190) NOT NULL UNIQUE,
telefon VARCHAR(20)
) ENGINE=InnoDB;
CREATE TABLE buyurtmalar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
mijoz_id INT UNSIGNED NOT NULL,
holat ENUM('yangi','tolangan','yetkazildi','bekor') NOT NULL DEFAULT 'yangi',
yaratilgan TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_buyurtma_mijoz
FOREIGN KEY (mijoz_id) REFERENCES mijozlar (id)
ON DELETE RESTRICT ON UPDATE CASCADE,
KEY idx_mijoz (mijoz_id),
KEY idx_holat (holat, yaratilgan)
) ENGINE=InnoDB;
-- Ko'p-ko'p: bitta buyurtmada ko'p mahsulot
CREATE TABLE buyurtma_elementlari (
buyurtma_id INT UNSIGNED NOT NULL,
mahsulot_id INT UNSIGNED NOT NULL,
soni SMALLINT UNSIGNED NOT NULL DEFAULT 1,
narx DECIMAL(12,2) NOT NULL, -- sotib olish paytidagi narx
PRIMARY KEY (buyurtma_id, mahsulot_id),
FOREIGN KEY (buyurtma_id) REFERENCES buyurtmalar (id) ON DELETE CASCADE,
FOREIGN KEY (mahsulot_id) REFERENCES mahsulotlar (id) ON DELETE RESTRICT
) ENGINE=InnoDB;
buyurtma_elementlari da narx takrorlanadi?Mahsulot narxi vaqt o'tishi bilan o'zgaradi. Agar buyurtmada faqat
mahsulot_id saqlansa, eski chekni ochganda bugungi narx ko'rinadi -
bu noto'g'ri.
Shuning uchun sotib olish paytidagi narx buyurtma bilan birga saqlanadi. Bu "tarixiy ma'lumot" deb ataladi va normalizatsiya qoidasidan ataylab chetlashish.
Tashqi kalitlarni ko'rish #
-- Jadvalning to'liq ta'rifi
SHOW CREATE TABLE buyurtmalar\G
-- Barcha tashqi kalitlar
SELECT
TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME,
REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_SCHEMA = 'dokon';
kutubxona bazasini to'liq bog'langan sxemaga aylantiring:
mualliflarvakitoblarorasida bir-ko'p bog'lanish yarating (FOREIGN KEY).ON DELETE RESTRICTqo'ying va muallifi bor muallifni o'chirishga urinib ko'ring.oquvchilarjadvalini yarating.ijaralaroraliq jadvalini yarating:kitob_id,oquvchi_id,olingan_sana,qaytarilgan_sana.- Unda tarkibiy birlamchi kalit ishlating.
- Mavjud bo'lmagan
muallif_idbilan kitob qo'shishga urinib ko'ring - xatoni o'qing. SHOW CREATE TABLEbilan barcha cheklovlarni ko'ring.- Sxemani qog'ozda chizing: jadvallar, kalitlar va bog'lanishlar.
Xulosa #
- Birlamchi kalit (PK) qatorni yagona aniqlaydi, tashqi kalit (FK) boshqa jadvalga ishora qiladi.
- Tashqi kalit har doim "ko'p" tomonda turadi.
- 1:N - eng keng tarqalgan; N:M oraliq jadval orqali amalga oshiriladi.
- Oraliq jadval qo'shimcha ma'lumot (baho, sana, narx) ham saqlashi mumkin.
ON DELETE CASCADEbilan ehtiyot bo'ling - zanjir bo'ylab ko'p yozuv o'chishi mumkin.- Tashqi kalitlar referensial butunlikni ta'minlaydi - noto'g'ri ma'lumot kirmaydi.
- Cheklovlarni faqat kodda emas, bazada ham qo'ying.
- Tarixiy ma'lumot (sotib olish narxi) ataylab takrorlanishi mumkin.
Keyingi bo'limda bog'langan jadvallardan birgalikda ma'lumot olishni - JOIN ni o'rganamiz.
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.