10-bo‘lim

Jadvallar orasidagi bog'lanishlar

Birlamchi va tashqi kalitlar, bir-ko'p, ko'p-ko'p va bir-bir munosabatlari, referensial butunlik.

🕑 11 daqiqa o‘qish 📄 763 so‘z 👁 5 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Muammo: takrorlanuvchi ma'lumot
  2. Yechim: alohida jadvallar + kalit
  3. Kalit turlari
  4. Bog'lanish turlari
  5. 1. Bir-ko'p (1:N) - eng keng tarqalgan
  6. 2. Ko'p-ko'p (N:M) - oraliq jadval bilan
  7. 3. Bir-bir (1:1) - kamdan-kam
  8. ON DELETE va ON UPDATE
  9. Tashqi kalit nimani himoya qiladi?
  10. Bog'langan ma'lumotni o'qish
  11. To'liq sxema misoli
  12. Tashqi kalitlarni ko'rish
  13. Xulosa

Relatsion bazaning butun kuchi bog'lanishlarda. Bir jadvaldagi qator boshqasidagi qatorga ishora qiladi.

Muammo: takrorlanuvchi ma'lumot #

SQL
-- 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)
);
idmijoz_ismmijoz_telefonmahsulot
1Husanboy Qodirov+998901234567Klaviatura
2Husanboy Qodirov+998901234567Sichqoncha
3Husanboy Qodirov+998901234567Monitor

Muammolar:

MuammoIzoh
TakrorlanishBir ma'lumot 3 marta saqlanmoqda
Yangilash anomaliyasiTelefon o'zgarsa - 3 joyda o'zgartirish kerak
NomuvofiqlikBir joyda o'zgartirib, boshqasini unutish
O'chirish anomaliyasiBuyurtmani o'chirsak - mijoz haqidagi ma'lumot ham yo'qoladi

Yechim: alohida jadvallar + kalit #

SQL
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;
mijozlar id (PK) ism telefon 1 Husanboy +99890... 2 Sardor +99891... buyurtmalar id mijoz_id (FK) mahsulot 1 1 Klaviatura 2 1 Sichqoncha 3 2 Monitor mijoz_id → mijozlar.id Mijoz ma'lumoti FAQAT BIR MARTA saqlanadi
Tashqi kalit (FK) boshqa jadvaldagi birlamchi kalitga (PK) ishora qiladi

Kalit turlari #

KalitVazifasi
Birlamchi kalit (PK)Qatorni yagona aniqlaydi
Tashqi kalit (FK)Boshqa jadvaldagi PK ga ishora qiladi
Nomzod kalitPK bo'la oladigan boshqa noyob ustun (email)
Tarkibiy kalitBir 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.

SQL
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;
Tashqi kalit "ko'p" tomonda turadi

Har doim shunday: talabalar.guruh_idguruhlar.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.

SQL
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;
talabalar id (PK) ism talaba_fan talaba_id (FK) fan_id (FK) baho fanlar id (PK) nomi 1 : N N : 1 Ko'p-ko'p bog'lanish ikkita bir-ko'p bog'lanishga bo'linadi
Oraliq jadval qo'shimcha ma'lumot (baho, sana) ham saqlashi mumkin
SQL
-- 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 #

SQL
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;
1:1 qachon kerak?
  • 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?

QiymatXatti-harakat
RESTRICTBog'liq yozuv bo'lsa o'chirishga ruxsat bermaydi (standart)
CASCADEBog'liq yozuvlar ham o'chiriladi
SET NULLTashqi kalit NULL ga o'rnatiladi
NO ACTIONRESTRICT bilan bir xil
SQL
-- 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'ling
SQL
DELETE 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? #

SQL
-- Mavjud bo'lmagan guruhga talaba qo'shishga urinish
INSERT INTO talabalar (guruh_id, ism) VALUES (999, 'Test');
Natija
ERROR 1452 (23000): Cannot add or update a child row:
a foreign key constraint fails
SQL
-- Talabasi bor guruhni o'chirishga urinish (RESTRICT bilan)
DELETE FROM guruhlar WHERE id = 1;
Natija
ERROR 1451 (23000): Cannot delete or update a parent row:
a foreign key constraint fails
Bu "referensial butunlik" deb ataladi

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 #

SQL
-- 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 #

SQL
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;
Nima uchun 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 #

SQL
-- 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';
Amaliy topshiriq

kutubxona bazasini to'liq bog'langan sxemaga aylantiring:

  1. mualliflar va kitoblar orasida bir-ko'p bog'lanish yarating (FOREIGN KEY).
  2. ON DELETE RESTRICT qo'ying va muallifi bor muallifni o'chirishga urinib ko'ring.
  3. oquvchilar jadvalini yarating.
  4. ijaralar oraliq jadvalini yarating: kitob_id, oquvchi_id, olingan_sana, qaytarilgan_sana.
  5. Unda tarkibiy birlamchi kalit ishlating.
  6. Mavjud bo'lmagan muallif_id bilan kitob qo'shishga urinib ko'ring - xatoni o'qing.
  7. SHOW CREATE TABLE bilan barcha cheklovlarni ko'ring.
  8. 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 CASCADE bilan 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.

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.