12-bo‘lim
Cheklovlar
NOT NULL, UNIQUE, CHECK va DEFAULT cheklovlari, ularni nomlash, ilova kodi bilan taqqoslash va cheklov qo'shish tartibi.
Ushbu bo‘lim mundarijasi
Cheklov - ma'lumotlar bazasining o'zida yozilgan qoida. Uni hech qanday dastur, skript yoki qo'lda kiritish buza olmaydi.
Nima uchun kodda emas #
To'rt asosiy cheklov #
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);
SELECT id, ism, yosh, maosh, holat FROM xodimlar ORDER BY id;
+----+----------+------+------------+-------+
| id | ism | yosh | maosh | holat |
+----+----------+------+------------+-------+
| 1 | Husanboy | 25 | 8000000.00 | faol |
| 2 | Malika | 30 | 9500000.00 | faol |
+----+----------+------+------------+-------+
NOT NULL va DEFAULT #
-- Majburiy ustunni tashlab ketish
INSERT INTO xodimlar (email, yosh) VALUES ('[email protected]', 25);
ERROR 1364 (HY000): Field 'ism' doesn't have a default value
-- 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';
+--------+-------+-------+
| ism | maosh | holat |
+--------+-------+-------+
| Kamola | 0.00 | faol |
+--------+-------+-------+
DEFAULT - hujjat hamdirholat ENUM(...) NOT NULL DEFAULT 'faol'
Bu qator ikki narsani aytadi:
- Yangi xodim odatda faol bo'ladi;
- 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:
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:
INSERT INTO xodimlar (email, ism, yosh, holat)
VALUES ('[email protected]', 'Test', 25, NULL); -- xato: holat NOT NULL
UNIQUE #
INSERT INTO xodimlar (email, ism, yosh)
VALUES ('[email protected]', 'Boshqa odam', 40);
ERROR 1062 (23000): Duplicate entry '[email protected]' for key 'email'
-- 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;
+----------+------------+----------+
| 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 |
+----------+------------+----------+
-- Bir kunda ikkinchi marta belgilash mumkin emas
INSERT INTO davomat (xodim_id, sana, kelgan) VALUES (1, '2026-09-10', '14:00:00');
ERROR 1062 (23000): Duplicate entry '1-2026-09-10' for key 'uq_xodim_sana'
UNIQUE - biznes qoidasini sxemaga yozishBu naqsh juda kuchli. Ba'zi misollar:
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:
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:
try {
$db->insert(...);
} catch (DuplicateKeyException $e) {
// allaqachon mavjud
}
CHECK #
INSERT INTO xodimlar (email, ism, yosh) VALUES ('[email protected]', 'Yosh', 15);
ERROR 4025 (23000): CONSTRAINT `chk_yosh` failed for `maktab`.`xodimlar`
INSERT INTO xodimlar (email, ism, yosh, maosh)
VALUES ('[email protected]', 'Test', 30, -100);
ERROR 4025 (23000): CONSTRAINT `chk_maosh` failed for `maktab`.`xodimlar`
INSERT INTO xodimlar (email, ism, yosh) VALUES ('notogri', 'Test', 30);
ERROR 4025 (23000): CONSTRAINT `chk_email` failed for `maktab`.`xodimlar`
-- 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;
+-----------+--------------------------+
| nomi | shart |
+-----------+--------------------------+
| chk_email | `email` like '%@%.%' |
| chk_maosh | `maosh` >= 0 |
| chk_yosh | `yosh` between 18 and 70 |
+-----------+--------------------------+
CHECK - qo'llab-quvvatlanishi versiyaga bog'liq| Tizim | CHECK |
|---|---|
| MariaDB 10.2+ | Ishlaydi |
| MySQL 8.0.16+ | Ishlaydi |
| MySQL 5.7 va oldin | Jimgina e'tiborsiz qoldiriladi |
| PostgreSQL | Har doim ishlagan |
| SQLite | Ishlaydi |
MySQL 5.7 dagi xatti-harakat ayniqsa xavfli: CHECK yozilgan,
xato bermaydi, lekin hech narsa tekshirmaydi. Dasturchi
himoya bor deb o'ylaydi.
Versiyangizni tekshiring:
SELECT VERSION();
CHECK cheklovlari nimalar uchun yaxshi:
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 (
SELECTishlatib bo'lmaydi); - O'zgaruvchan funksiyalar (
NOW(),RAND()); - Murakkab biznes mantiq.
Ular uchun trigger yoki ilova kodi kerak.
Cheklovlarni nomlash #
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';
+------+
| nomi |
+------+
| yosh |
+------+
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:
CONSTRAINT chk_yosh CHECK (yosh BETWEEN 18 AND 70)
Xato xabari darhol tushunarli bo'ladi:
CONSTRAINT `chk_yosh` failed
Nomlash kelishuvi:
| Prefiks | Cheklov 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:
ALTER TABLE xodimlar DROP CONSTRAINT chk_yosh;
Mavjud jadvalga cheklov qo'shish #
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);
-- Mavjud ma'lumot cheklovni buzsa, qo'shib bo'lmaydi
ALTER TABLE mahsulotlar ADD CONSTRAINT chk_narx CHECK (narx > 0);
ERROR 4025 (23000): CONSTRAINT `chk_narx` failed for `maktab`.`mahsulotlar`
-- Avval ma'lumotni tozalash kerak
SELECT id, nom, narx FROM mahsulotlar WHERE narx <= 0;
+----+-------------+---------+
| id | nom | narx |
+----+-------------+---------+
| 3 | Buzuq yozuv | -500.00 |
+----+-------------+---------+
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';
+----------+
| nomi |
+----------+
| chk_narx |
+----------+
Katta jadvalga cheklov qo'shish - xavfli amal:
ALTER TABLEbutun jadvalni tekshiradi - million qatorda bu daqiqalar oladi;- Shu vaqt davomida jadval qulflangan bo'lishi mumkin;
- Bitta buzuq qator butun amalni bekor qiladi.
To'g'ri tartib:
-- 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 #
"Cheklov bor bo'lsa, kodda tekshirish kerakmi?" - ha, lekin boshqa maqsad uchun:
| Daraja | Vazifasi |
|---|---|
| Ilova | Foydalanuvchiga tushunarli xabar berish |
| Ma'lumotlar bazasi | Ma'lumot buzilmasligini kafolatlash |
Foydalanuvchi buni ko'rmasligi kerak:
ERROR 4025 (23000): CONSTRAINT `chk_yosh` failed
U buni ko'rishi kerak:
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:
- Ilovada tekshiring - tajriba uchun;
- Bazada cheklov qo'ying - kafolat uchun;
- Baza xatosini ushlab, tushunarli xabarga aylantiring.
Uchinchi qadam ikkalasini bog'laydi: cheklov nomini xato xabariga moslashtiring.
Cheklovlarni ko'rish #
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;
+-----------+-------------+
| nomi | turi |
+-----------+-------------+
| PRIMARY | PRIMARY KEY |
| chk_email | CHECK |
| chk_maosh | CHECK |
| chk_yosh | CHECK |
| email | UNIQUE |
+-----------+-------------+
- To'rt turdagi cheklovli jadval yarating.
NOT NULLustunni tashlab ketishga urinib ko'ring.DEFAULTqiymat qanday ishlashini ko'rsating.- Takroriy
UNIQUEqiymat kiritishga urining. - Kompozit
UNIQUEbilan biznes qoidasini yozing. - Poyga holati nima uchun paydo bo'lishini tushuntiring.
- Uch xil
CHECKcheklovini buzib ko'ring. - Cheklovga nom berish nima uchun muhimligini ayting.
- Buzuq ma'lumotli jadvalga cheklov qo'shishga urining.
- 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.
DEFAULTqarorni bir joyda mustahkamlaydi va hujjat bo'ladi.- Kompozit
UNIQUEpoyga holatidan himoya qiladi. - "Avval tekshirib, keyin yozish" naqshiga tayanmang.
CHECKMariaDB 10.2+ va MySQL 8.0.16+ da ishlaydi.- MySQL 5.7
CHECKni 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.
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.