UPDATE va DELETE — shartlar bilan, xavfli holatlar
Muammodan boshlaylik
Juma kuni kechqurun. Dasturchi bitta mahsulot narxini o'zgartirmoqchi:
UPDATE mahsulotlar SET narx = 99000;
Enter. Query OK, 48213 rows affected.
WHERE unutildi. Do'kondagi barcha 48 213 ta mahsulot endi 99 000 so'm. MacBook ham, qopqoq ham. Sayt ishlab turibdi, mijozlar xarid qilyapti.
UPDATE va DELETE — SQL dagi eng kuchli va eng xavfli buyruqlar. Bu darsda ularni xavfsiz ishlatishni o'rganamiz.
UPDATE — o'zgartirish
UPDATE mahsulotlar
SET narx = 11900000
WHERE id = 1;
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
Rows matched—WHEREga mos kelgan qatorlarChanged— haqiqatan o'zgarganlar (qiymat allaqachon shu bo'lsa — o'zgarmaydi)
Bir nechta ustun
UPDATE mijozlar
SET telefon = '+998909998877', shahar = 'Toshkent'
WHERE id = 3;
Mavjud qiymatdan hisoblash
-- Omborga 10 ta qo'shildi
UPDATE mahsulotlar SET soni = soni + 10 WHERE id = 5;
-- Aksessuarlar 15% arzonlashdi
UPDATE mahsulotlar SET narx = ROUND(narx * 0.85) WHERE toifa_id = 3;
-- Buyurtma yetkazildi
UPDATE buyurtmalar SET holat = 'yetkazildi' WHERE id = 2 AND holat = 'yolda';
Oxirgi misolda AND holat = 'yolda' — himoya: faqat "yo'lda" bo'lgan buyurtmani "yetkazildi" qilish mumkin. Bekor qilingan buyurtma tasodifan yetkazilgan bo'lib qolmaydi. Rows matched: 0 bo'lsa — ilova "bu holatni o'zgartirib bo'lmaydi" deb biladi.
Atomar o'zgartirish
-- ❌ Ikki so'rov — race condition
SELECT soni FROM mahsulotlar WHERE id = 1; -- 4
-- (ilovada: 4 - 1 = 3)
UPDATE mahsulotlar SET soni = 3 WHERE id = 1;
-- ✅ Bitta atomar so'rov
UPDATE mahsulotlar SET soni = soni - 1 WHERE id = 1 AND soni > 0;
Birinchi usulda ikki xaridor bir vaqtda sotib olsa — ikkalasi ham 4 ni o'qiydi, ikkalasi ham 3 yozadi. Ikkita telefon sotildi, ombordan bittasi kamaydi. Ikkinchi usulda MySQL o'zi navbat bilan bajaradi. AND soni > 0 — omborda yo'q mahsulotni sotib bo'lmaydi (Rows matched: 0).
DELETE — o'chirish
DELETE FROM mijozlar WHERE id = 4;
Shartli:
-- 1 yildan eski loglar
DELETE FROM kirish_loglari WHERE vaqt < NOW() - INTERVAL 1 YEAR;
-- Bekor qilingan, 30 kundan eski buyurtmalar
DELETE FROM buyurtmalar WHERE holat = 'bekor' AND yaratilgan < NOW() - INTERVAL 30 DAY;
Foreign key bor bo'lsa — 7-darsdagi qoidalar ishlaydi: RESTRICT to'xtatadi, CASCADE bolalarni ham o'chiradi.
Xavfsizlik odatlari
1. Avval SELECT
UPDATE yoki DELETE dan oldin — aynan shu WHERE bilan SELECT:
SELECT id, nom, narx FROM mahsulotlar WHERE toifa_id = 3;
-- 2 rows — ha, aynan shular
UPDATE mahsulotlar SET narx = ROUND(narx * 0.85) WHERE toifa_id = 3;
-- 2 rows affected — mos keldi
Natija soni kutilganidan farq qilsa — to'xtang.
2. Tranzaksiya ichida
START TRANSACTION;
UPDATE mahsulotlar SET narx = ROUND(narx * 1.1) WHERE toifa_id = 1;
-- Query OK, 2 rows affected — kutilgandek
SELECT nom, narx FROM mahsulotlar WHERE toifa_id = 1; -- tekshirish
COMMIT; -- hammasi to'g'ri — saqlash
-- yoki
ROLLBACK; -- xato — hammasini qaytarish
COMMIT dan oldin hech narsa yakuniy emas. Tranzaksiyalar 36-darsda batafsil.
3. LIMIT bilan cheklash
DELETE FROM kirish_loglari WHERE vaqt < '2025-01-01' LIMIT 1000;
Million qatorni bir so'rovda o'chirish — jadvalni uzoq qulflaydi va saytni sekinlashtiradi. 1000 tadan bo'lib, sikl bilan o'chirish — xavfsizroq.
4. Safe updates rejimi
SET SQL_SAFE_UPDATES = 1;
UPDATE mahsulotlar SET narx = 99000;
-- ERROR 1175: You are using safe update mode and you tried to update a table
-- without a WHERE that uses a KEY column.
Workbench da standart yoqilgan. Terminalda ham yoqib qo'yish mumkin:
mysql --safe-updates -u root -p
5. Production da — faqat backup bilan
Qo'lda katta UPDATE/DELETE dan oldin — backup yoki hech bo'lmasa jadval nusxasi:
CREATE TABLE mahsulotlar_backup_20261102 AS SELECT * FROM mahsulotlar;
Soft delete — o'chirmasdan o'chirish
Ko'p tizimlarda ma'lumot haqiqatan o'chirilmaydi — "o'chirilgan" deb belgilanadi:
ALTER TABLE mijozlar ADD COLUMN ochirilgan DATETIME NULL;
-- "O'chirish"
UPDATE mijozlar SET ochirilgan = NOW() WHERE id = 4;
-- Faol mijozlar
SELECT * FROM mijozlar WHERE ochirilgan IS NULL;
-- Tiklash
UPDATE mijozlar SET ochirilgan = NULL WHERE id = 4;
| Hard delete | Soft delete | |
|---|---|---|
| Tiklash | Faqat backup dan | Bitta UPDATE |
| Tarix, audit | Yo'qoladi | Saqlanadi |
| Foreign key muammolari | Bor | Yo'q |
| Kamchilik | — | Har so'rovda WHERE ochirilgan IS NULL ni unutmaslik; UNIQUE email bilan muammo |
Laravel dagi SoftDeletes trait aynan shunday ishlaydi.
[!INFO] Shaxsiy ma'lumotlar qonunlari foydalanuvchi so'rasa, uning ma'lumotlarini haqiqatan o'chirishni talab qilishi mumkin. Bunday holatda soft delete yetarli emas — shaxsiy maydonlar anonimlashtiriladi.
Boshqa jadvalga qarab o'zgartirish
-- Bekor qilingan buyurtmadagi mahsulotlarni omborga qaytarish
UPDATE mahsulotlar m
JOIN buyurtma_qatorlari q ON q.mahsulot_id = m.id
SET m.soni = m.soni + q.soni
WHERE q.buyurtma_id = 4;
-- Hech qachon buyurtma bermagan mijozlarni o'chirish
DELETE m FROM mijozlar m
LEFT JOIN buyurtmalar b ON b.mijoz_id = m.id
WHERE b.id IS NULL;
JOIN lar 15-16 darslarda batafsil.
Nima uchun shunday?
Nima uchun SQL WHERE siz UPDATE ga ruxsat beradi — xavfli bo'lsa, nega taqiqlanmagan?
Chunki ba'zan bu aynan kerak: "barcha narxlarni 10% oshirish" yoki "barcha foydalanuvchilarni yangi tarifga o'tkazish". SQL sizni dasturchi sifatida hurmat qiladi va buyruqni so'zma-so'z bajaradi. Himoya — sizning odatlaringizda: avval SELECT, tranzaksiya, safe mode, backup. Bu odatlar bir marta sizni katta falokatdan qutqaradi.
Xulosa
Eslab qoling:
UPDATE t SET ustun = qiymat WHERE shart—WHEREsiz hamma qator o'zgaradiDELETE FROM t WHERE shart—WHEREsiz hamma qator o'chadi- Avval o'sha
WHEREbilanSELECTqiling - Muhim o'zgarishlar —
START TRANSACTION...COMMIT/ROLLBACK - Atomar:
SET soni = soni - 1 WHERE soni > 0— o'qib, keyin yozmang SQL_SAFE_UPDATES = 1— tasodifiy ommaviy o'zgarishdan himoya- Soft delete:
ochirilgan DATETIME NULL
Keyingi dars
13-dars: Aggregate funksiyalar — COUNT, SUM, AVG, MIN, MAX