UPDATE va DELETE — shartlar bilan, xavfli holatlar

~15 daq · MySQL · DML — Ma'lumot Boshqarish

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 — WHERE ga mos kelgan qatorlar
  • Changed — 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 — WHERE siz hamma qator o'zgaradi
  • DELETE FROM t WHERE shart — WHERE siz hamma qator o'chadi
  • Avval o'sha WHERE bilan SELECT qiling
  • 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