INSERT — bir va bir nechta qator, INSERT IGNORE, ON DUPLICATE KEY
Muammodan boshlaylik
Tuzilma tayyor — jadvallar bo'sh. Endi ularni ma'lumot bilan to'ldirish kerak: yangi mijoz ro'yxatdan o'tdi, yangi mahsulot keldi, buyurtma berildi. Bu ishni INSERT bajaradi.
Oddiy ko'rinadi, lekin real hayotda savollar paydo bo'ladi: 10 000 ta mahsulotni Excel dan qanday tez yuklash kerak? Mahsulot allaqachon bor bo'lsa — xato berish kerakmi yoki yangilash? Bu darsda shularga javob beramiz.
Asosiy sintaksis
INSERT INTO mijozlar (ism, email, telefon, shahar)
VALUES ('Dilshod Aliyev', 'dilshod@mail.uz', '+998901234567', 'Toshkent');
- Ustunlar ro'yxati va qiymatlar ro'yxati bir xil tartibda
- Matn va sanalar — bittalik tirnoqda
'...' - Sonlar — tirnoqsiz
NULL— tirnoqsiz
Ko'rsatilmagan ustunlar DEFAULT qiymatini oladi (id — avtomatik, yaratilgan — hozirgi vaqt).
Ustunlarni har doim yozing
-- ❌ Ishlaydi, lekin xavfli
INSERT INTO toifalar VALUES (NULL, 'Planshetlar');
-- ✅
INSERT INTO toifalar (nom) VALUES ('Planshetlar');
Ustunlarsiz variant jadvaldagi barcha ustunlarni aniq tartibda kutadi. Ertaga jadvalga yangi ustun qo'shilsa — bu so'rov buziladi.
Bir nechta qator — bir so'rovda
INSERT INTO mahsulotlar (toifa_id, nom, narx, soni) VALUES
(1, 'Xiaomi Redmi Note 13', 2900000, 20),
(1, 'Google Pixel 8', 8500000, 3),
(3, 'Zaryadlovchi 65W', 350000, 40);
Bu uchta alohida INSERT dan ancha tez: serverga bitta so'rov, bitta tranzaksiya, indekslar bir marta yangilanadi. 10 000 qatorni yuklashda farq — soniyalar va daqiqalar.
[!TIP] Juda ko'p qator bo'lsa — 500-1000 tadan bo'laklarga bo'ling. Bitta ulkan so'rov
max_allowed_packetchegarasiga urilishi mumkin.
Yangi qatorning ID si
INSERT INTO buyurtmalar (mijoz_id) VALUES (2);
SELECT LAST_INSERT_ID();
LAST_INSERT_ID() — joriy ulanishda oxirgi yaratilgan AUTO_INCREMENT qiymati. Boshqa foydalanuvchilar bir vaqtda qator qo'shsa ham — sizga faqat o'zingiznikini qaytaradi. Shuning uchun xavfsiz.
Buyurtma va uning qatorlarini yaratish:
INSERT INTO buyurtmalar (mijoz_id) VALUES (2);
SET @bid = LAST_INSERT_ID();
INSERT INTO buyurtma_qatorlari (buyurtma_id, mahsulot_id, soni, narx) VALUES
(@bid, 5, 1, 3100000),
(@bid, 6, 2, 120000);
@bid — sessiya o'zgaruvchisi. Ilovada (PHP, Node) bu lastInsertId() yoki insertId orqali olinadi.
Boshqa jadvaldan nusxalash: INSERT ... SELECT
CREATE TABLE arxiv_buyurtmalar LIKE buyurtmalar;
INSERT INTO arxiv_buyurtmalar
SELECT * FROM buyurtmalar WHERE yaratilgan < '2026-01-01';
So'rov natijasi to'g'ridan-to'g'ri boshqa jadvalga yoziladi — ilovaga olib chiqmasdan.
Takrorlanish muammosi
email — UNIQUE. Mavjud email bilan qo'shsak:
INSERT INTO mijozlar (ism, email) VALUES ('Aziz', 'aziz@mail.uz');
-- ERROR 1062: Duplicate entry 'aziz@mail.uz' for key 'mijozlar.email'
Bu ko'pincha to'g'ri xatti-harakat. Lekin ba'zan boshqacha kerak bo'ladi. Uch variant bor.
1. INSERT IGNORE — jimgina o'tkazib yuborish
INSERT IGNORE INTO mijozlar (ism, email) VALUES
('Aziz', 'aziz@mail.uz'), -- bor — o'tkazib yuboriladi
('Yangi', 'yangi@mail.uz'); -- yo'q — qo'shiladi
Xato o'rniga ogohlantirish. Import paytida "borlarini tashlab ket, yangilarini qo'sh" uchun qulay.
[!WARNING]
IGNOREfaqat dublikatni emas, boshqa xatolarni ham yutib yuboradi: noto'g'ri tur,NOT NULLbuzilishi — qiymat jimgina "tuzatiladi". Ehtiyotkorlik bilan ishlating vaSHOW WARNINGS;bilan tekshiring.
2. ON DUPLICATE KEY UPDATE — bor bo'lsa yangilash (upsert)
Ombor ma'lumoti har kuni yetkazib beruvchidan keladi. Mahsulot bor bo'lsa — narx va sonini yangilash, yo'q bo'lsa — qo'shish:
ALTER TABLE mahsulotlar ADD COLUMN sku VARCHAR(30) NULL UNIQUE;
INSERT INTO mahsulotlar (sku, nom, narx, soni)
VALUES ('APL-IP15', 'iPhone 15', 12300000, 10)
AS yangi
ON DUPLICATE KEY UPDATE
narx = yangi.narx,
soni = mahsulotlar.soni + yangi.soni;
skubo'yicha mahsulot yo'q → yangi qator- Bor → narx yangilanadi, soni qo'shiladi (omborga yangi partiya keldi)
AS yangi— kiritilayotgan qiymatlarga nom (MySQL 8.0.19+)
Eski versiyalarda VALUES(narx) yozilardi — u eskirgan, lekin eski kodda ko'p uchraydi:
ON DUPLICATE KEY UPDATE narx = VALUES(narx);
Ko'rish hisoblagichi uchun klassik misol:
INSERT INTO sahifa_korishlari (sahifa, soni) VALUES ('/php', 1)
ON DUPLICATE KEY UPDATE soni = soni + 1;
Bitta so'rov — tekshirish ham, qo'shish ham, yangilash ham. Ikki foydalanuvchi bir vaqtda kirsa ham to'g'ri ishlaydi.
3. REPLACE — o'chirib, qaytadan qo'shish
REPLACE INTO mahsulotlar (sku, nom, narx, soni) VALUES ('APL-IP15', 'iPhone 15', 12300000, 10);
Dublikat bo'lsa — eski qatorni o'chiradi, keyin yangisini qo'shadi.
[!WARNING]
REPLACExavfli: eski qator o'chiriladi, shuning uchun yangiidberiladi, ko'rsatilmagan ustunlarDEFAULTga qaytadi, vaON DELETE CASCADEbo'lsa — bog'liq qatorlar ham o'chadi. Deyarli har doimON DUPLICATE KEY UPDATEyaxshiroq.
Fayldan yuklash
CSV fayldan million qatorni yuklashning eng tez yo'li:
LOAD DATA LOCAL INFILE '/yol/mahsulotlar.csv'
INTO TABLE mahsulotlar
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(sku, nom, narx, soni);
IGNORE 1 LINES — sarlavha qatorini tashlab ketish. Bu INSERT lardan o'nlab marta tez. (local_infile sozlamasi yoqilgan bo'lishi kerak.)
Nima uchun shunday?
Nima uchun SELECT qilib "bormi?" deb tekshirib, keyin INSERT yoki UPDATE qilish noto'g'ri?
So'rov A: SELECT ... WHERE sku='X' → yo'q
So'rov B: SELECT ... WHERE sku='X' → yo'q
So'rov A: INSERT sku='X' → ✅
So'rov B: INSERT sku='X' → ❌ Duplicate entry
Tekshirish va yozish orasida boshqa so'rov "suqilib kirishi" mumkin — bu race condition deyiladi. ON DUPLICATE KEY UPDATE esa tekshirish va yozishni bitta atomar amalda bajaradi — orasiga hech kim kira olmaydi.
Xulosa
Eslab qoling:
INSERT INTO t (ustunlar) VALUES (...)— ustunlarni doim yozing- Ko'p qator — bitta
INSERTda, vergul bilan LAST_INSERT_ID()— yangi qatoridsi, faqat sizning ulanishingiznikiINSERT ... SELECT— jadvaldan jadvalgaINSERT IGNORE— dublikatni o'tkazish (boshqa xatolarni ham yutadi!)ON DUPLICATE KEY UPDATE— upsert;REPLACEdan xavfsizroqLOAD DATA INFILE— katta CSV uchun
Keyingi dars
10-dars: SELECT — WHERE, AND, OR, NOT, BETWEEN, IN, LIKE, IS NULL