6-bo‘lim

Birinchi normal shakl (1NF)

Atomar qiymat nima, ko'p qiymatli va takrorlanuvchi ustunlar, 1NF ga keltirish va JSON ustunlar haqida.

🕑 16 daqiqa o‘qish 📄 861 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. 1NF talabi
  2. Birinchi buzilish: ko'p qiymatli ustun
  3. 1NF ga keltirish
  4. Nima yutdik
  5. Ikkinchi buzilish: takrorlanuvchi ustunlar
  6. To'g'ri yechim
  7. Atomarlik nisbiy tushuncha
  8. JSON ustunlar - istisno bormi?
  9. Xulosa

Normalizatsiya - takrorlanishni bosqichma-bosqich yo'q qilish usuli. Birinchi bosqich eng oddiy, lekin eng ko'p buziladigan.

1NF talabi #

Birinchi normal shakl Har katakda AYNAN BITTA qiymat bo'lishi kerak va har ustun bir xil turdagi ma'lumotni saqlashi kerak 1NF buzilgan telefonlar: '901234567, 911112233' fan1, fan2, fan3 ustunlari manzil: 'Namangan, Navoiy 12' 1NF bajarilgan telefonlar - alohida jadval yozilishlar - bog'lovchi jadval shahar, kocha, uy - alohida ustun
Atomarlik - qiymatni bo'lishga ehtiyoj bo'lmasligi

Birinchi buzilish: ko'p qiymatli ustun #

SQL
CREATE TABLE mijozlar_yomon (
    id         INT PRIMARY KEY,
    ism        VARCHAR(100),
    telefonlar VARCHAR(255),
    manzil     VARCHAR(255)
);

INSERT INTO mijozlar_yomon VALUES
    (1, 'Husanboy Qodirov', '901234567,935556677', 'Namangan, Navoiy 12'),
    (2, 'Malika Yusupova',  '911112233',           'Farg''ona, Mustaqillik 5'),
    (3, 'Kamola Rasulova',  '',                    'Andijon, Bobur 8');
SQL
-- "935556677 raqami kimga tegishli?" - qanday topamiz?
SELECT ism, telefonlar
FROM mijozlar_yomon
WHERE telefonlar LIKE '%935556677%';
Natija
+------------------+---------------------+
| ism              | telefonlar          |
+------------------+---------------------+
| Husanboy Qodirov | 901234567,935556677 |
+------------------+---------------------+
LIKE '%...%' indeksdan foydalana olmaydi

Yuqoridagi so'rov ishlaydi, lekin butun jadvalni o'qiydi.

Indeks so'zning boshidan qidiradi - xuddi lug'atdagi kabi. LIKE 'abc%' indeksdan foydalanadi, LIKE '%abc%' esa yo'q.

Million qatorli jadvalda farq:

So'rovVaqti
WHERE raqam = '935556677' (indeksli)~1 ms
WHERE telefonlar LIKE '%935556677%'~2000 ms

Yana bir jiddiy muammo - noto'g'ri moslik:

SQL
WHERE telefonlar LIKE '%5556677%'

Bu 935556677 ni ham, 15556677 ni ham topadi. Chegara belgilari yo'q.

Va nihoyat: '901234567,935556677' da bo'shliq bo'lsa (', ') yoki bo'lmasa - qidiruv natijasi o'zgaradi. Ma'lumot formati kafolatlanmagan.

1NF ga keltirish #

SQL
CREATE TABLE mijozlar (
    id     INT PRIMARY KEY AUTO_INCREMENT,
    ism    VARCHAR(100) NOT NULL,
    shahar VARCHAR(50)  NOT NULL,
    kocha  VARCHAR(100) NOT NULL,
    uy     VARCHAR(20)  NOT NULL
);

CREATE TABLE telefonlar (
    id       INT PRIMARY KEY AUTO_INCREMENT,
    mijoz_id INT NOT NULL,
    raqam    VARCHAR(20) NOT NULL,
    turi     ENUM('mobil', 'uy', 'ish') NOT NULL DEFAULT 'mobil',
    UNIQUE (raqam),
    FOREIGN KEY (mijoz_id) REFERENCES mijozlar(id) ON DELETE CASCADE
);

INSERT INTO mijozlar (ism, shahar, kocha, uy) VALUES
    ('Husanboy Qodirov', 'Namangan', 'Navoiy',       '12'),
    ('Malika Yusupova',  'Farg''ona', 'Mustaqillik', '5'),
    ('Kamola Rasulova',  'Andijon',  'Bobur',        '8');

INSERT INTO telefonlar (mijoz_id, raqam, turi) VALUES
    (1, '901234567', 'mobil'),
    (1, '935556677', 'ish'),
    (2, '911112233', 'mobil');

Endi raqam bo'yicha aniq qidiruv mumkin:

SQL
SELECT m.ism, t.raqam, t.turi
FROM mijozlar m
JOIN telefonlar t ON t.mijoz_id = m.id
WHERE t.raqam = '935556677';
Natija
+------------------+-----------+------+
| ism              | raqam     | turi |
+------------------+-----------+------+
| Husanboy Qodirov | 935556677 | ish  |
+------------------+-----------+------+

Endi qidiruv aniq tenglik bo'yicha ketmoqda va indeksdan foydalanadi.

Nima yutdik #

SQL
-- 1. Telefon turini bilamiz
SELECT m.ism, COUNT(t.id) AS raqamlar, GROUP_CONCAT(t.turi ORDER BY t.id) AS turlari
FROM mijozlar m
LEFT JOIN telefonlar t ON t.mijoz_id = m.id
GROUP BY m.id, m.ism
ORDER BY m.id;
Natija
+------------------+----------+-----------+
| ism              | raqamlar | turlari   |
+------------------+----------+-----------+
| Husanboy Qodirov |        2 | mobil,ish |
| Malika Yusupova  |        1 | mobil     |
| Kamola Rasulova  |        0 | NULL      |
+------------------+----------+-----------+
SQL
-- 2. Takroriy raqamni tizim rad etadi
INSERT INTO telefonlar (mijoz_id, raqam) VALUES (2, '901234567');
Natija
ERROR 1062 (23000): Duplicate entry '901234567' for key 'raqam'
SQL
-- 3. Shahar bo'yicha guruhlash oson
SELECT shahar, COUNT(*) AS mijozlar
FROM mijozlar
GROUP BY shahar
ORDER BY shahar;
Natija
+----------+----------+
| shahar   | mijozlar |
+----------+----------+
| Andijon  |        1 |
| Farg'ona |        1 |
| Namangan |        1 |
+----------+----------+
Manzilni qanchalik bo'lish kerak?

Bu muvozanat masalasi:

Bo'lish darajasiQachon
Bitta manzil matniFaqat chop etish uchun kerak bo'lsa
shahar + qolganiShahar bo'yicha filtr kerak bo'lsa
shahar, kocha, uyYetkazib berish, statistika
+ viloyat_id (jadval)Rasmiy hisobot, standart ro'yxat

Qoida: ma'lumot bo'yicha qidirasizmi yoki guruhlaysizmi? Agar ha - alohida ustun kerak.

Ortiqcha bo'lish ham zarar: hech kim uy raqamini alohida so'ramasa, uni ajratish faqat murakkablik qo'shadi.

Xalqaro loyihalarda manzil formati mamlakatlarga qarab juda farq qiladi - shuning uchun ko'pincha erkin matn maydonlari va bitta mamlakat kodi ishlatiladi.

Ikkinchi buzilish: takrorlanuvchi ustunlar #

SQL
CREATE TABLE talabalar_yomon (
    id   INT PRIMARY KEY,
    ism  VARCHAR(100),
    fan1 VARCHAR(50),
    fan2 VARCHAR(50),
    fan3 VARCHAR(50)
);

INSERT INTO talabalar_yomon VALUES
    (1, 'Husanboy', 'Matematika', 'Fizika', 'Ingliz tili'),
    (2, 'Malika',   'Matematika', NULL,     NULL);

-- "Fizikaga yozilganlarni top" - uchala ustunni tekshirish kerak
SELECT ism FROM talabalar_yomon
WHERE fan1 = 'Fizika' OR fan2 = 'Fizika' OR fan3 = 'Fizika';
Natija
+----------+
| ism      |
+----------+
| Husanboy |
+----------+
Takrorlanuvchi ustunlar - yashirin massiv

fan1, fan2, fan3 - bu aslida massiv, faqat ustunlarga yoyilgan.

Muammolari:

MuammoIzoh
Chegara qattiqTo'rtinchi fan kerak bo'lsa - ALTER TABLE
Har so'rov uzunOR zanjiri, har yangi ustun bilan o'sadi
Indeks samarasizHar ustunga alohida indeks kerak
NULL lar ko'pBitta fan olgan talabada 2 ta bo'sh ustun
Tartib ma'nosizfan1 va fan2 orasida farq bormi?
Sanash qiyinCOUNT o'rniga qo'lda tekshiruv

Xuddi shu naqsh boshqa ko'rinishlarda ham uchraydi:

SQL
telefon1, telefon2, telefon3
manzil_uy, manzil_ish
rasm_1 ... rasm_10

Har safar javob bir xil: alohida jadval.

Belgi: ustun nomida raqam bo'lsa - deyarli har doim 1NF buzilgan.

To'g'ri yechim #

SQL
CREATE TABLE fanlar (
    id  INT PRIMARY KEY AUTO_INCREMENT,
    nom VARCHAR(50) NOT NULL UNIQUE
);

CREATE TABLE talabalar (
    id  INT PRIMARY KEY AUTO_INCREMENT,
    ism VARCHAR(100) NOT NULL
);

CREATE TABLE yozilishlar (
    talaba_id INT NOT NULL,
    fan_id    INT NOT NULL,
    PRIMARY KEY (talaba_id, fan_id),
    FOREIGN KEY (talaba_id) REFERENCES talabalar(id),
    FOREIGN KEY (fan_id)    REFERENCES fanlar(id)
);

INSERT INTO fanlar (nom) VALUES ('Matematika'), ('Fizika'), ('Ingliz tili');
INSERT INTO talabalar (ism) VALUES ('Husanboy'), ('Malika');
INSERT INTO yozilishlar VALUES (1, 1), (1, 2), (1, 3), (2, 1);

Endi so'rov qisqa va indeksli:

SQL
SELECT t.ism
FROM talabalar t
JOIN yozilishlar y ON y.talaba_id = t.id
JOIN fanlar f      ON f.id = y.fan_id
WHERE f.nom = 'Fizika';
Natija
+----------+
| ism      |
+----------+
| Husanboy |
+----------+
SQL
-- To'rtinchi fan qo'shish - ALTER TABLE kerak emas
INSERT INTO fanlar (nom) VALUES ('Tarix');
INSERT INTO yozilishlar VALUES (2, 4);

SELECT t.ism, COUNT(*) AS fanlar_soni
FROM talabalar t
JOIN yozilishlar y ON y.talaba_id = t.id
GROUP BY t.id, t.ism
ORDER BY t.id;
Natija
+----------+-------------+
| ism      | fanlar_soni |
+----------+-------------+
| Husanboy |           3 |
| Malika   |           2 |
+----------+-------------+

Atomarlik nisbiy tushuncha #

SQL
-- Ism atomarmi? Bu ehtiyojga bog'liq
CREATE TABLE variantlar (
    id           INT PRIMARY KEY AUTO_INCREMENT,
    toliq_ism    VARCHAR(200),
    ism          VARCHAR(100),
    familiya     VARCHAR(100),
    otasining_ismi VARCHAR(100)
);

INSERT INTO variantlar (toliq_ism, ism, familiya, otasining_ismi) VALUES
    ('Qodirov Husanboy Baxtiyor o''g''li', 'Husanboy', 'Qodirov', 'Baxtiyor');

SELECT
    toliq_ism,
    CONCAT(familiya, ' ', LEFT(ism, 1), '.') AS qisqartma
FROM variantlar;
Natija
+----------------------------------+------------+
| toliq_ism                        | qisqartma  |
+----------------------------------+------------+
| Qodirov Husanboy Baxtiyor o'g'li | Qodirov H. |
+----------------------------------+------------+
"Atomar" - texnik emas, kontekstga bog'liq

1NF "qiymat bo'linmas bo'lsin" deydi. Lekin bo'linmaslik sizning ehtiyojingizga bog'liq:

Ma'lumotAtomarmi?
'Husanboy Qodirov'Faqat chop etsangiz - ha
'Husanboy Qodirov'Familiya bo'yicha saralasangiz - yo'q
'2026-09-10'Odatda ha
'2026-09-10'Oy bo'yicha guruhlasangiz - DATE turi buni beradi
'#FF5733'Rang kodi - ha

Amaliy savol: shu qiymatning bir qismi bo'yicha qidirasizmi yoki saralaysizmi?

  • Ha → alohida ustun kerak;
  • Yo'q → bitta ustun yetarli.

Vergulli ro'yxat esa har doim 1NF buzilishi, chunki uning elementlari mustaqil mavjudliklar.

JSON ustunlar - istisno bormi? #

SQL
CREATE TABLE mahsulotlar (
    id         INT PRIMARY KEY AUTO_INCREMENT,
    nom        VARCHAR(100) NOT NULL,
    narx       DECIMAL(10,2) NOT NULL,
    xossalar   JSON
);

INSERT INTO mahsulotlar (nom, narx, xossalar) VALUES
    ('Noutbuk', 8000000, '{"ram": "16GB", "ekran": "15.6", "rang": "kulrang"}'),
    ('Telefon', 4000000, '{"ram": "8GB", "kamera": "48MP"}');

SELECT nom,
       JSON_VALUE(xossalar, '$.ram') AS ram,
       JSON_VALUE(xossalar, '$.kamera') AS kamera
FROM mahsulotlar
ORDER BY id;
Natija
+---------+------+--------+
| nom     | ram  | kamera |
+---------+------+--------+
| Noutbuk | 16GB | NULL   |
| Telefon | 8GB  | 48MP   |
+---------+------+--------+
JSON - qulay, lekin qimmat

JSON ustun 1NF ni rasman buzadi, lekin ba'zan asosli:

JSON o'rinli bo'lgan holatlar:

HolatNima uchun
Har mahsulotning turlicha xossalariUstun yaratib bo'lmaydi
Tashqi API javobini saqlashTuzilma o'zgarishi mumkin
Sozlamalar, jurnal ma'lumotiQidirilmaydi
Prototip bosqichiSxema hali aniq emas

JSON dan qochish kerak bo'lgan holatlar:

HolatNima uchun
Ma'lumot bo'yicha qidiriladiIndeks murakkab, sekin
Tashqi kalit kerakJSON ichida FK bo'lmaydi
Qiymat majburiyNOT NULL ichkarida ishlamaydi
Hisobot tuziladiJOIN va agregatsiya og'ir

Nima yo'qotiladi:

  • Tur tekshiruvi - "ram": 16 va "ram": "16GB" ikkalasi o'tadi;
  • Cheklovlar - CHECK, UNIQUE ishlamaydi;
  • Tashqi kalit - yo'q;
  • Oddiy indeks - generatsiyalangan ustun kerak.

Qoida: avval oddiy ustun, JSON faqat haqiqatan dinamik ma'lumot uchun. "Keyin kerak bo'ladi" degan sabab bilan JSON qo'ymang.

Amaliy topshiriq
  1. Vergulli telefon ro'yxatidan raqam qidiring.
  2. LIKE '%...%' nima uchun indeksdan foydalanmasligini ayting.
  3. Telefonlarni alohida jadvalga chiqaring.
  4. Telefon turini qo'shib, guruhlab chiqaring.
  5. Takroriy raqam kiritishga urinib ko'ring.
  6. fan1, fan2, fan3 ustunli jadvaldan qidiring.
  7. Takrorlanuvchi ustunlarning oltita muammosini sanang.
  8. Bog'lovchi jadvalga o'tkazib, to'rtinchi fanni qo'shing.
  9. "Atomar" tushunchasi nima uchun nisbiy ekanini tushuntiring.
  10. JSON ustun o'rinli va o'rinsiz bo'lgan holatlarni ayting.

Xulosa #

  • 1NF: har katakda aynan bitta qiymat.
  • Vergulli ro'yxat - eng ko'p uchraydigan 1NF buzilishi.
  • LIKE '%...%' indeksdan foydalana olmaydi.
  • Raqamli ustun nomlari (fan1, fan2) - yashirin massiv belgisi.
  • Takrorlanuvchi ustunlar qattiq chegara qo'yadi.
  • "Atomar" kontekstga bog'liq - qidirasizmi yoki saralaysizmi?
  • Manzilni ehtiyojga qarab bo'ling, ortiqcha emas.
  • JSON 1NF ni buzadi - faqat haqiqatan dinamik ma'lumot uchun.
  • JSON da tur tekshiruvi, cheklov va tashqi kalit yo'qoladi.

Keyingi bo'limda ikkinchi normal shaklni ko'ramiz.

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.