12-bo‘lim

Cheklovlar

NOT NULL, UNIQUE, CHECK va DEFAULT cheklovlari, ularni nomlash, ilova kodi bilan taqqoslash va cheklov qo'shish tartibi.

🕑 23 daqiqa o‘qish 📄 734 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Nima uchun kodda emas
  2. To'rt asosiy cheklov
  3. NOT NULL va DEFAULT
  4. UNIQUE
  5. CHECK
  6. Cheklovlarni nomlash
  7. Mavjud jadvalga cheklov qo'shish
  8. Cheklov va ilova kodi - ikkalasi ham kerak
  9. Cheklovlarni ko'rish
  10. Xulosa

Cheklov - ma'lumotlar bazasining o'zida yozilgan qoida. Uni hech qanday dastur, skript yoki qo'lda kiritish buza olmaydi.

Nima uchun kodda emas #

Ma'lumotga kim yozadi? Veb ilova Mobil API Import skripti Admin qo'lda Migratsiya CHEKLOVLAR yagona darvoza Ma'lumot har doim to'g'ri Qoida kodda bo'lsa - har bir yo'lda takrorlanishi kerak
Ma'lumotlar bazasi - ma'lumotga yagona kirish nuqtasi

To'rt asosiy cheklov #

SQL
CREATE TABLE xodimlar (
    id        INT PRIMARY KEY AUTO_INCREMENT,
    email     VARCHAR(100) NOT NULL UNIQUE,
    ism       VARCHAR(100) NOT NULL,
    yosh      TINYINT UNSIGNED NOT NULL,
    maosh     DECIMAL(10,2) NOT NULL DEFAULT 0,
    holat     ENUM('faol', 'tatil', 'ishdan_ketgan') NOT NULL DEFAULT 'faol',
    yaratilgan DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT chk_yosh   CHECK (yosh BETWEEN 18 AND 70),
    CONSTRAINT chk_maosh  CHECK (maosh >= 0),
    CONSTRAINT chk_email  CHECK (email LIKE '%@%.%')
);

INSERT INTO xodimlar (email, ism, yosh, maosh) VALUES
    ('[email protected]', 'Husanboy', 25, 8000000),
    ('[email protected]',   'Malika',   30, 9500000);
SQL
SELECT id, ism, yosh, maosh, holat FROM xodimlar ORDER BY id;
Natija
+----+----------+------+------------+-------+
| id | ism      | yosh | maosh      | holat |
+----+----------+------+------------+-------+
|  1 | Husanboy |   25 | 8000000.00 | faol  |
|  2 | Malika   |   30 | 9500000.00 | faol  |
+----+----------+------+------------+-------+

NOT NULL va DEFAULT #

SQL
-- Majburiy ustunni tashlab ketish
INSERT INTO xodimlar (email, yosh) VALUES ('[email protected]', 25);
Natija
ERROR 1364 (HY000): Field 'ism' doesn't have a default value
SQL
-- DEFAULT bor ustunlarni tashlab ketish mumkin
INSERT INTO xodimlar (email, ism, yosh) VALUES ('[email protected]', 'Kamola', 22);

SELECT ism, maosh, holat FROM xodimlar WHERE ism = 'Kamola';
Natija
+--------+-------+-------+
| ism    | maosh | holat |
+--------+-------+-------+
| Kamola |  0.00 | faol  |
+--------+-------+-------+
DEFAULT - hujjat hamdir
SQL
holat  ENUM(...) NOT NULL DEFAULT 'faol'

Bu qator ikki narsani aytadi:

  1. Yangi xodim odatda faol bo'ladi;
  2. Bu qiymatni kod aytmasa ham to'g'ri bo'ladi.

DEFAULT bo'lmasa, har bir INSERT yozgan dasturchi bu qarorni qayta qabul qilishi kerak - va ular turlicha qaror qabul qilishadi.

Foydali standart qiymatlar:

SQL
yaratilgan  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
yangilangan DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
            ON UPDATE CURRENT_TIMESTAMP,
faolmi      BOOLEAN  NOT NULL DEFAULT TRUE,
soni        INT      NOT NULL DEFAULT 0,
uuid        CHAR(36) NOT NULL DEFAULT (UUID())

Diqqat: DEFAULT faqat ustun umuman ko'rsatilmaganda qo'llanadi. Aniq NULL yozsangiz - xato bo'ladi:

SQL
INSERT INTO xodimlar (email, ism, yosh, holat)
VALUES ('[email protected]', 'Test', 25, NULL);   -- xato: holat NOT NULL

UNIQUE #

SQL
INSERT INTO xodimlar (email, ism, yosh)
VALUES ('[email protected]', 'Boshqa odam', 40);
Natija
ERROR 1062 (23000): Duplicate entry '[email protected]' for key 'email'
SQL
-- Kompozit UNIQUE: bir kunda bir xodim bir marta belgilanadi
CREATE TABLE davomat (
    id        INT PRIMARY KEY AUTO_INCREMENT,
    xodim_id  INT NOT NULL,
    sana      DATE NOT NULL,
    kelgan    TIME NOT NULL,
    CONSTRAINT uq_xodim_sana UNIQUE (xodim_id, sana),
    FOREIGN KEY (xodim_id) REFERENCES xodimlar(id)
);

INSERT INTO davomat (xodim_id, sana, kelgan) VALUES
    (1, '2026-09-10', '09:00:00'),
    (2, '2026-09-10', '08:45:00'),
    (1, '2026-09-11', '09:05:00');

SELECT xodim_id, sana, kelgan FROM davomat ORDER BY id;
Natija
+----------+------------+----------+
| xodim_id | sana       | kelgan   |
+----------+------------+----------+
|        1 | 2026-09-10 | 09:00:00 |
|        2 | 2026-09-10 | 08:45:00 |
|        1 | 2026-09-11 | 09:05:00 |
+----------+------------+----------+
SQL
-- Bir kunda ikkinchi marta belgilash mumkin emas
INSERT INTO davomat (xodim_id, sana, kelgan) VALUES (1, '2026-09-10', '14:00:00');
Natija
ERROR 1062 (23000): Duplicate entry '1-2026-09-10' for key 'uq_xodim_sana'
Kompozit UNIQUE - biznes qoidasini sxemaga yozish

Bu naqsh juda kuchli. Ba'zi misollar:

SQL
UNIQUE (foydalanuvchi_id, maqola_id)   -- bir maqolaga bir like
UNIQUE (sinf_id, kun, juftlik)         -- bir vaqtda bir dars
UNIQUE (buyurtma_id, mahsulot_id)      -- bir buyurtmada bir marta
UNIQUE (kod, yil)                      -- yil ichida noyob kod

Bunday qoida kodda yozilganda poyga holati paydo bo'ladi:

Natija
1-so'rov: SELECT ... WHERE xodim_id=1 AND sana='2026-09-10'  -> yo'q
2-so'rov: SELECT ... WHERE xodim_id=1 AND sana='2026-09-10'  -> yo'q
1-so'rov: INSERT  -> muvaffaqiyat
2-so'rov: INSERT  -> TAKROR YOZILDI

UNIQUE cheklov bilan ikkinchi INSERT xato beradi - qoida jismonan buzilmaydi.

Shuning uchun "avval tekshirib, keyin yozish" naqshiga tayanmang. Cheklov qo'ying va xatoni ushlang:

PHP
try {
    $db->insert(...);
} catch (DuplicateKeyException $e) {
    // allaqachon mavjud
}

CHECK #

SQL
INSERT INTO xodimlar (email, ism, yosh) VALUES ('[email protected]', 'Yosh', 15);
Natija
ERROR 4025 (23000): CONSTRAINT `chk_yosh` failed for `maktab`.`xodimlar`
SQL
INSERT INTO xodimlar (email, ism, yosh, maosh)
VALUES ('[email protected]', 'Test', 30, -100);
Natija
ERROR 4025 (23000): CONSTRAINT `chk_maosh` failed for `maktab`.`xodimlar`
SQL
INSERT INTO xodimlar (email, ism, yosh) VALUES ('notogri', 'Test', 30);
Natija
ERROR 4025 (23000): CONSTRAINT `chk_email` failed for `maktab`.`xodimlar`
SQL
-- Cheklovlar sxemada ko'rinadi
SELECT CONSTRAINT_NAME AS nomi, CHECK_CLAUSE AS shart
FROM information_schema.CHECK_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = DATABASE() AND TABLE_NAME = 'xodimlar'
ORDER BY BINARY CONSTRAINT_NAME;
Natija
+-----------+--------------------------+
| nomi      | shart                    |
+-----------+--------------------------+
| chk_email | `email` like '%@%.%'     |
| chk_maosh | `maosh` >= 0             |
| chk_yosh  | `yosh` between 18 and 70 |
+-----------+--------------------------+
CHECK - qo'llab-quvvatlanishi versiyaga bog'liq
TizimCHECK
MariaDB 10.2+Ishlaydi
MySQL 8.0.16+Ishlaydi
MySQL 5.7 va oldinJimgina e'tiborsiz qoldiriladi
PostgreSQLHar doim ishlagan
SQLiteIshlaydi

MySQL 5.7 dagi xatti-harakat ayniqsa xavfli: CHECK yozilgan, xato bermaydi, lekin hech narsa tekshirmaydi. Dasturchi himoya bor deb o'ylaydi.

Versiyangizni tekshiring:

SQL
SELECT VERSION();

CHECK cheklovlari nimalar uchun yaxshi:

SQL
CHECK (narx >= 0)
CHECK (tugash_sana > boshlanish_sana)
CHECK (chegirma BETWEEN 0 AND 100)
CHECK (holat IN ('yangi', 'tolangan', 'bekor'))
CHECK (CHAR_LENGTH(telefon) >= 9)

Nimalar uchun yaramaydi:

  • Boshqa jadvalga murojaat (SELECT ishlatib bo'lmaydi);
  • O'zgaruvchan funksiyalar (NOW(), RAND());
  • Murakkab biznes mantiq.

Ular uchun trigger yoki ilova kodi kerak.

Cheklovlarni nomlash #

SQL
CREATE TABLE nomsiz (
    id  INT PRIMARY KEY,
    yosh INT CHECK (yosh > 0)
);

SELECT CONSTRAINT_NAME AS nomi
FROM information_schema.CHECK_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = DATABASE() AND TABLE_NAME = 'nomsiz';
Natija
+------+
| nomi |
+------+
| yosh |
+------+
Cheklovga har doim nom bering

Nomsiz cheklov avtomatik nom oladi va u:

  • Tushunarsiz bo'lishi mumkin (xodimlar_chk_1);
  • Versiyalar orasida farq qilishi mumkin;
  • Xato xabarida foydasiz ko'rinadi.

Aniq nom bilan:

SQL
CONSTRAINT chk_yosh CHECK (yosh BETWEEN 18 AND 70)

Xato xabari darhol tushunarli bo'ladi:

Natija
CONSTRAINT `chk_yosh` failed

Nomlash kelishuvi:

PrefiksCheklov turi
pk_Birlamchi kalit
fk_Tashqi kalit
uq_UNIQUE
chk_CHECK
idx_Indeks

Masalan: fk_buyurtma_mijoz, uq_xodim_sana, chk_narx_musbat.

Bu ayniqsa migratsiyada muhim - cheklovni o'chirish uchun uning nomi kerak:

SQL
ALTER TABLE xodimlar DROP CONSTRAINT chk_yosh;

Mavjud jadvalga cheklov qo'shish #

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

INSERT INTO mahsulotlar (nom, narx) VALUES
    ('Noutbuk', 8000000),
    ('Sichqoncha', 150000),
    ('Buzuq yozuv', -500);
SQL
-- Mavjud ma'lumot cheklovni buzsa, qo'shib bo'lmaydi
ALTER TABLE mahsulotlar ADD CONSTRAINT chk_narx CHECK (narx > 0);
Natija
ERROR 4025 (23000): CONSTRAINT `chk_narx` failed for `maktab`.`mahsulotlar`
SQL
-- Avval ma'lumotni tozalash kerak
SELECT id, nom, narx FROM mahsulotlar WHERE narx <= 0;
Natija
+----+-------------+---------+
| id | nom         | narx    |
+----+-------------+---------+
|  3 | Buzuq yozuv | -500.00 |
+----+-------------+---------+
SQL
DELETE FROM mahsulotlar WHERE narx <= 0;

ALTER TABLE mahsulotlar ADD CONSTRAINT chk_narx CHECK (narx > 0);

SELECT CONSTRAINT_NAME AS nomi
FROM information_schema.CHECK_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = DATABASE() AND TABLE_NAME = 'mahsulotlar';
Natija
+----------+
| nomi     |
+----------+
| chk_narx |
+----------+
Ishlab turgan tizimga cheklov qo'shish tartibi

Katta jadvalga cheklov qo'shish - xavfli amal:

  1. ALTER TABLE butun jadvalni tekshiradi - million qatorda bu daqiqalar oladi;
  2. Shu vaqt davomida jadval qulflangan bo'lishi mumkin;
  3. Bitta buzuq qator butun amalni bekor qiladi.

To'g'ri tartib:

SQL
-- 1. Muammoli qatorlar bormi?
SELECT COUNT(*) FROM mahsulotlar WHERE narx <= 0;

-- 2. Ularni tuzatish yoki o'chirish (ilova bilan kelishib)
UPDATE mahsulotlar SET narx = 1 WHERE narx <= 0;

-- 3. Ilova kodini yangilash - endi u ham tekshirsin
-- 4. Faqat shundan keyin cheklov qo'shish
ALTER TABLE mahsulotlar ADD CONSTRAINT chk_narx CHECK (narx > 0);

Uchinchi qadamni tashlab ketmang: cheklov qo'shilgach, uni buzuvchi kod xato bilan qulaydi. Foydalanuvchi tushunarsiz xato ko'rmasligi uchun ilova avval yangilanishi kerak.

Kam yuklangan vaqtda (kechasi) bajaring va ALTER ni qaytarish rejasini tayyorlab qo'ying.

Cheklov va ilova kodi - ikkalasi ham kerak #

Takrorlanish emas, ikki xil vazifa

"Cheklov bor bo'lsa, kodda tekshirish kerakmi?" - ha, lekin boshqa maqsad uchun:

DarajaVazifasi
IlovaFoydalanuvchiga tushunarli xabar berish
Ma'lumotlar bazasiMa'lumot buzilmasligini kafolatlash

Foydalanuvchi buni ko'rmasligi kerak:

Natija
ERROR 4025 (23000): CONSTRAINT `chk_yosh` failed

U buni ko'rishi kerak:

Natija
Yosh 18 dan 70 gacha bo'lishi kerak

Lekin ilova tekshiruvi yetarli emas, chunki ma'lumotga boshqa yo'llar ham bor: import skripti, admin paneli, boshqa xizmat, qo'lda UPDATE.

Amaliy naqsh:

  1. Ilovada tekshiring - tajriba uchun;
  2. Bazada cheklov qo'ying - kafolat uchun;
  3. Baza xatosini ushlab, tushunarli xabarga aylantiring.

Uchinchi qadam ikkalasini bog'laydi: cheklov nomini xato xabariga moslashtiring.

Cheklovlarni ko'rish #

SQL
SELECT
    tc.CONSTRAINT_NAME AS nomi,
    tc.CONSTRAINT_TYPE AS turi
FROM information_schema.TABLE_CONSTRAINTS tc
WHERE tc.TABLE_SCHEMA = DATABASE() AND tc.TABLE_NAME = 'xodimlar'
ORDER BY BINARY tc.CONSTRAINT_NAME;
Natija
+-----------+-------------+
| nomi      | turi        |
+-----------+-------------+
| PRIMARY   | PRIMARY KEY |
| chk_email | CHECK       |
| chk_maosh | CHECK       |
| chk_yosh  | CHECK       |
| email     | UNIQUE      |
+-----------+-------------+
Amaliy topshiriq
  1. To'rt turdagi cheklovli jadval yarating.
  2. NOT NULL ustunni tashlab ketishga urinib ko'ring.
  3. DEFAULT qiymat qanday ishlashini ko'rsating.
  4. Takroriy UNIQUE qiymat kiritishga urining.
  5. Kompozit UNIQUE bilan biznes qoidasini yozing.
  6. Poyga holati nima uchun paydo bo'lishini tushuntiring.
  7. Uch xil CHECK cheklovini buzib ko'ring.
  8. Cheklovga nom berish nima uchun muhimligini ayting.
  9. Buzuq ma'lumotli jadvalga cheklov qo'shishga urining.
  10. Ma'lumotni tozalab, cheklovni muvaffaqiyatli qo'shing.

Xulosa #

  • Cheklov - bazadagi qoida, uni hech qanday kod buza olmaydi.
  • Ma'lumotga ko'p yo'l bor: ilova, skript, admin, migratsiya.
  • DEFAULT qarorni bir joyda mustahkamlaydi va hujjat bo'ladi.
  • Kompozit UNIQUE poyga holatidan himoya qiladi.
  • "Avval tekshirib, keyin yozish" naqshiga tayanmang.
  • CHECK MariaDB 10.2+ va MySQL 8.0.16+ da ishlaydi.
  • MySQL 5.7 CHECK ni jimgina e'tiborsiz qoldiradi.
  • Cheklovga har doim nom bering (chk_, uq_, fk_).
  • Mavjud jadvalga cheklov qo'shishdan oldin ma'lumotni tozalang.
  • Ilova tushunarli xabar, baza kafolat beradi - ikkalasi ham kerak.

Keyingi bo'limda tashqi kalitlar va referensial butunlikni 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.