Constraints — PRIMARY KEY, NOT NULL, UNIQUE, DEFAULT, CHECK
Muammodan boshlaylik
Saytingizda ro'yxatdan o'tish formasi bor. PHP kodida tekshiruvlar yozilgan: email bo'sh emas, takrorlanmaydi, yosh musbat. Lekin:
- Admin panel boshqa dasturchi tomonidan yozilgan — u tekshiruvni unutgan
- Mobil ilova API orqali to'g'ridan-to'g'ri yozadi — u yerda boshqa qoidalar
- Kimdir Workbench da qo'lda
INSERTqildi - Ikki foydalanuvchi bir soniyada bir xil email bilan ro'yxatdan o'tdi — ikkala PHP so'rov ham "email bo'sh" deb tekshirdi
Natijada bazada: bo'sh emaillar, dublikat akkauntlar, -5 yoshli foydalanuvchilar.
Cheklovlar — qoidalarni bazaning o'zida belgilash. Ma'lumot qaysi yo'l bilan kelishidan qat'i nazar — baza noto'g'ri ma'lumotni qabul qilmaydi. Bu oxirgi va eng ishonchli himoya chizig'i.
NOT NULL — majburiy maydon
CREATE TABLE mijozlar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
ism VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL,
telefon VARCHAR(20) NULL -- ixtiyoriy
);
INSERT INTO mijozlar (ism) VALUES ('Aziz');
-- ERROR 1364: Field 'email' doesn't have a default value
Qoida: har bir ustunni avval NOT NULL deb tasavvur qiling. Faqat "bu ma'lumot haqiqatan ham bo'lmasligi mumkin" bo'lsa — NULL.
[!WARNING]
NOT NULLbo'sh matnni ('') to'xtatmaydi.''— buNULLemas, uzunligi nol bo'lgan matn. Bo'sh matnni ham taqiqlash uchun —CHECK(pastda).
UNIQUE — takrorlanmas qiymat
CREATE TABLE mijozlar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
telefon VARCHAR(20) NULL UNIQUE
);
INSERT INTO mijozlar (email) VALUES ('aziz@mail.uz');
INSERT INTO mijozlar (email) VALUES ('aziz@mail.uz');
-- ERROR 1062: Duplicate entry 'aziz@mail.uz' for key 'mijozlar.email'
Ikki bir vaqtdagi so'rov muammosi ham hal: baza ikkinchisini albatta rad etadi. Ilovada 1062 xatosini ushlab, "bu email band" deb ko'rsatasiz (PHP kursi, 38-dars).
UNIQUE ustunda NULL lar bir nechta bo'lishi mumkin — chunki NULL "noma'lum", ikki noma'lum teng emas. Telefonsiz 100 ta mijoz — muammo emas.
Bir nechta ustun bo'yicha
CREATE TABLE baholar (
talaba_id INT UNSIGNED NOT NULL,
fan_id INT UNSIGNED NOT NULL,
ball TINYINT UNSIGNED NOT NULL,
UNIQUE (talaba_id, fan_id) -- bitta talaba bitta fandan bitta baho
);
Alohida-alohida takrorlanishi mumkin, lekin juftlik noyob.
PRIMARY KEY
Primary key = NOT NULL + UNIQUE + jadvalda faqat bitta.
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
Murakkab (composite) primary key — bir nechta ustundan:
CREATE TABLE mahsulot_teglar (
mahsulot_id INT UNSIGNED NOT NULL,
teg_id INT UNSIGNED NOT NULL,
PRIMARY KEY (mahsulot_id, teg_id)
);
Bunday jadvallar ko'p-ko'p munosabatda ishlatiladi (19-dars).
DEFAULT — standart qiymat
CREATE TABLE buyurtmalar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
holat VARCHAR(20) NOT NULL DEFAULT 'yangi',
chegirma TINYINT UNSIGNED NOT NULL DEFAULT 0,
yaratilgan DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
yangilangan DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
kod CHAR(36) NOT NULL DEFAULT (UUID())
);
INSERT INTO buyurtmalar () VALUES ();
SELECT * FROM buyurtmalar;
-- holat = 'yangi', chegirma = 0, yaratilgan = hozirgi vaqt, kod = '3f2a...'
DEFAULT CURRENT_TIMESTAMP— yaratilgan vaqt avtomatikON UPDATE CURRENT_TIMESTAMP— qator har o'zgarganda vaqt yangilanadiDEFAULT (ifoda)— MySQL 8.0.13+ da qavs ichida funksiya ham mumkin
CHECK — ixtiyoriy qoida (MySQL 8.0.16+)
CREATE TABLE mahsulotlar (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(200) NOT NULL,
narx INT UNSIGNED NOT NULL,
chegirmali_narx INT UNSIGNED NULL,
reyting TINYINT UNSIGNED NULL,
CONSTRAINT chk_nom_bosh_emas CHECK (TRIM(nom) <> ''),
CONSTRAINT chk_reyting CHECK (reyting BETWEEN 1 AND 5),
CONSTRAINT chk_chegirma CHECK (chegirmali_narx IS NULL OR chegirmali_narx < narx)
);
INSERT INTO mahsulotlar (nom, narx, reyting) VALUES ('Telefon', 1000, 7);
-- ERROR 3819: Check constraint 'chk_reyting' is violated.
INSERT INTO mahsulotlar (nom, narx, chegirmali_narx) VALUES ('Telefon', 1000, 1500);
-- ERROR 3819: Check constraint 'chk_chegirma' is violated.
CONSTRAINT nom — cheklovga nom berish. Xato xabarida aynan qaysi qoida buzilgani ko'rinadi va keyinchalik uni nomi bo'yicha o'chirish oson.
Bir nechta ustunni bog'laydigan qoidalar (chegirma < narx) — faqat CHECK bilan.
[!WARNING] MySQL 8.0.16 dan oldingi versiyalarda
CHECKsintaksisi qabul qilinardi, lekin e'tiborsiz qoldirilardi. Eski versiyada bo'lsangiz — qoida ishlamaydi va hech qanday ogohlantirish yo'q.SELECT VERSION();bilan tekshiring.
Cheklovlarni ko'rish
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = 'dokon' AND TABLE_NAME = 'mahsulotlar';
+-------------------+-----------------+
| CONSTRAINT_NAME | CONSTRAINT_TYPE |
+-------------------+-----------------+
| PRIMARY | PRIMARY KEY |
| chk_chegirma | CHECK |
| chk_nom_bosh_emas | CHECK |
| chk_reyting | CHECK |
+-------------------+-----------------+
information_schema — MySQL ning o'zi haqidagi ma'lumotlar bazasi: barcha jadvallar, ustunlar, indekslar shu yerda.
SQL mode — qat'iylik darajasi
SELECT @@sql_mode;
-- ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
STRICT_TRANS_TABLES — noto'g'ri qiymat kelsa xato beradi. Busiz MySQL jimgina "tuzatadi": 300 belgilik matnni 200 ga qisqartiradi, 'abc' ni 0 ga aylantiradi — faqat ogohlantirish bilan.
Eski loyihalar va ba'zi hostinglar strict mode ni o'chirib qo'yadi. O'chirmang — jimgina buzilgan ma'lumot xatodan ancha yomon.
Nima uchun shunday?
Nima uchun tekshiruvni ilovada ham, bazada ham qilish kerak — takrorlash emasmi?
Ular turli vazifani bajaradi. Ilovadagi tekshiruv — foydalanuvchi uchun: tushunarli xabar, qaysi maydonda xato, formani qayta to'ldirmaslik. Bazadagi cheklov — ma'lumot uchun: qaysi ilova, qaysi dasturchi, qaysi xato bilan yozmasin — buzilgan ma'lumot kirmaydi. Ilovalar keladi va ketadi (veb sayt, mobil ilova, admin panel, import skripti). Ma'lumot esa qoladi.
Xulosa
Eslab qoling:
NOT NULL— majburiy;''ni to'xtatmaydiUNIQUE— takrorlanmas;NULLlar bir nechta bo'lishi mumkin; bir nechta ustun bo'yicha hamPRIMARY KEY—NOT NULL+UNIQUE, jadvalda bittaDEFAULT— standart qiymat;CURRENT_TIMESTAMP,ON UPDATECHECK— ixtiyoriy qoida (8.0.16+);CONSTRAINT nombilan nomlang- Strict SQL mode ni o'chirmang
- Bazadagi cheklov — oxirgi himoya chizig'i
Keyingi dars
7-dars: FOREIGN KEY — CASCADE, SET NULL, RESTRICT