IlmHamroh
JavaScript Full-stack/26-qism. SQL va PostgreSQL18/64-dars17 daqiqa
Mundarija (28)

SQL UPDATE va DELETE: ma'lumotni xavfsiz o'zgartirish va o'chirish

Qisqacha: UPDATE jadval SET ustun = qiymat WHERE shart qatorlarni o'zgartiradi, DELETE FROM jadval WHERE shart — o'chiradi. WHERE ni unutsangiz — butun jadval o'zgaradi. Xavfsiz odat: avval xuddi shu WHERE bilan SELECT qiling, keyin BEGIN ichida o'zgartiring, RETURNING bilan natijani ko'ring va faqat to'g'ri bo'lsa COMMIT — aks holda ROLLBACK. Boshqa jadvalga qarab o'zgartirish — UPDATE … FROM va DELETE … USING; jadvalni butunlay bo'shatish — TRUNCATE.

Bu darsda

  • UPDATE … SET bilan bir yoki bir necha ustunni o'zgartirasiz, ifoda ishlatasiz.
  • DELETE bilan qator o'chirasiz va CASCADE zanjirini eslab qolasiz.
  • "SELECT → BEGIN → RETURNING → COMMIT/ROLLBACK" xavfsiz tartibini odat qilasiz.
  • UPDATE … FROM va DELETE … USING bilan boshqa jadval ma'lumotiga qarab o'zgartirasiz.
  • TRUNCATE va DELETE farqini, tashqi kalit bilan bog'liq tuzog'ini bilasiz.

Oldin bilishingiz kerak: SELECT va WHERE, INSERT va RETURNING, Foreign key va referential actions.

1. Nega bu kerak?

Vazifa bajarildi — bajarildi ni true qilish kerak. Foydalanuvchi matnni tahrirladi — matn o'zgaradi. Vazifa o'chirildi — qator ketadi. Har ilovada bu uch amal har kuni minglab marta bajariladi.

Lekin UPDATE va DELETE — SQL'ning eng xavfli buyruqlari. SELECT noto'g'ri bo'lsa — noto'g'ri natija ko'rasiz, xolos. UPDATE noto'g'ri bo'lsa — ma'lumot buziladi. Va psql "ishonchingiz komilmi?" deb so'ramaydi.

Dasturchilar orasida mashhur hikoya bor. Kimdir ishlab turgan (production) bazada yozadi:

sql
UPDATE foydalanuvchilar SET parol = '...'

…va WHERE id = 5 ni yozishga ulgurmay Enter'ni bosadi. Hamma foydalanuvchining paroli bir xil bo'lib qoladi. Bu hikoya har yili kimningdir boshidan o'tadi.

O'xshatish: jarroh. Yaxshi jarroh operatsiyadan oldin uch marta tekshiradi: bemor shumi, qaysi tomon, nima qilinadi. SQL'da ham shunday "tekshiruv ro'yxati" bor. Bu dars — o'sha ro'yxat.

2. UPDATE asoslari

2.1 SET va WHERE

Bu darsdagi hamma misol holat 15 bazasida, BEGIN … ROLLBACK ichida — baza o'zgarmaydi. Biz ishga tushirdik (PG 17.6, Windows 11):

sql
BEGIN;
UPDATE vazifalar
SET matn = matn || ' #shoshilinch', bajarildi = false
WHERE id = 29
RETURNING id, matn, bajarildi;

Natija:

text
BEGIN
 id |               matn               | bajarildi 
----+----------------------------------+-----------
 29 | Gaz to'lovi #to'lov #shoshilinch | f
(1 row)

UPDATE 1

Qismlar:

Qism Ma'nosi
UPDATE vazifalar Qaysi jadval
SET matn = …, bajarildi = false Qaysi ustunlar va yangi qiymatlar (vergul bilan)
WHERE id = 29 Qaysi qatorlar
RETURNING … O'zgargan qatorning yangi holati

matn || ' #shoshilinch' — || matnlarni ulaydi. O'ng tomondagi matn — eski qiymat. Ya'ni SET ifodalari o'zgarishdan oldingi qatorni ko'radi. Shuning uchun SET a = b, b = a ikki ustunni almashtiradi — JavaScript'dagidan farqli, vaqtinchalik o'zgaruvchi kerak emas.

UPDATE 1 — psql holati: 1 qator o'zgardi.

Qisqa misol: holatni teskarisiga almashtirish (NOT). Biz ishga tushirdik (PG 17.6):

sql
BEGIN;
UPDATE vazifalar SET bajarildi = NOT bajarildi
WHERE id IN (1, 2) RETURNING id, bajarildi;
ROLLBACK;

Natija:

text
BEGIN
 id | bajarildi
----+-----------
  1 | t
  2 | f
(2 rows)

UPDATE 2
ROLLBACK

Bu — ilovadagi "belgilash" tugmasi (checkbox) bazada.

2.2 Hech narsa topilmasa — xato emas

Biz ishga tushirdik (PG 17.6):

sql
UPDATE vazifalar SET bajarildi = true WHERE id = 999;

Natija:

text
UPDATE 0

999-vazifa yo'q, lekin xato ham yo'q — nol qator o'zgardi. Ilova uchun bu muhim signal: PATCH /vazifalar/999 so'rovida UPDATE 0 bo'lsa, server 404 Not Found qaytarishi kerak (25-qism, Xato javoblari). Node'da bu son rowCount deb keladi (node-postgres asoslari).

2.3 Cheklovlar UPDATE'da ham ishlaydi

CREATE TABLE darsidagi CHECK lar faqat INSERT ni emas, UPDATE ni ham tekshiradi. Biz ishga tushirdik (PG 17.6) — Dilnozaning hamma vazifasi matnini bo'shatishga urinish:

sql
UPDATE vazifalar SET matn = '' WHERE egasi_id = 2;

Natija:

text
ERROR:  new row for relation "vazifalar" violates check constraint "vazifalar_matn_check"
DETAIL:  Failing row contains (5, 2, , t, 2026-10-02 02:00:00+00).

Tarjimasi: "vazifalar jadvalidagi yangi qator vazifalar_matn_check ni buzadi". UPDATE uchun ham "yangi qator" deyilgani bejiz emas: PostgreSQL'da UPDATE aslida qatorning yangi nusxasini yozadi (bu haqda MVCC darsida). Dilnozaning 6 vazifasidan birinchisi (id 5) buzilishi bilanoq butun UPDATE bekor bo'ldi — hech qaysi qator o'zgarmadi.

Tekshirib ko'ring: UPDATE vazifalar SET bajarildi = true WHERE egasi_id = 1 AND bajarildi qancha qator o'zgartiradi va natija nima beradi?

Javob

Azizning 4 ta bajarilgan vazifasi — UPDATE 4. Lekin hech narsa amalda o'zgarmaydi: ular allaqachon true. PostgreSQL baribir 4 qatorni qayta yozadi. Shuning uchun WHERE ga AND NOT bajarildi qo'shish foydali — keraksiz yozuv bo'lmaydi va UPDATE N haqiqiy o'zgarishlar sonini ko'rsatadi.

3. DELETE asoslari

3.1 Qator o'chirish

sql
DELETE FROM vazifalar WHERE id = 29;

Sintaksis UPDATE dan ham sodda: qaysi jadval va qaysi qatorlar. RETURNING ham bor — o'chirilgan qatorlar ko'rinadi.

3.2 CASCADE'ni eslang

Foreign key darsida vazifalar_egasi_id_fkey ni ON DELETE CASCADE bilan yaratdik. Foydalanuvchi o'chirilsa nima bo'lishini ko'ramiz. Biz ishga tushirdik (PG 17.6, BEGIN … ROLLBACK ichida):

sql
BEGIN;
DELETE FROM foydalanuvchilar
WHERE email = 'aziz@example.com'
RETURNING id, ism;

SELECT count(*) AS qolgan_vazifalar FROM vazifalar;
ROLLBACK;

Natija:

text
BEGIN
 id |     ism      
----+--------------
  1 | Aziz Karimov
(1 row)

DELETE 1
 qolgan_vazifalar 
------------------
               31
(1 row)

ROLLBACK

DELETE 1 — "bitta qator". Haqiqatda esa 10 qator ketdi: Aziz va uning 9 vazifasi (40 − 9 = 31). RETURNING ham faqat foydalanuvchini ko'rsatdi. O'chirishdan oldin "bu qator kimlarni o'zi bilan olib ketadi?" deb o'ylang.

4. Xavfsiz o'zgartirish tartibi

4.1 To'rt qadam

flowchart TD
  A["1. SELECT ... WHERE<br/>nima o'zgaradi?"] --> B["2. BEGIN"]
  B --> C["3. UPDATE/DELETE ... WHERE<br/>RETURNING"]
  C --> D{"Son va qatorlar<br/>kutilgandekmi?"}
  D -->|ha| E["COMMIT"]
  D -->|yo'q| F["ROLLBACK"]

Diagrammadagi tarmoqlanishga qarang: COMMIT faqat tekshiruvdan keyin. Kanon (PostgreSQL 18.6) bu tartibni Azizning #o'qish vazifalarida ko'rsatadi.

1-qadam — avval ko'rish. O'zgartiradigan WHERE ni avval SELECT bilan ishga tushiring:

sql
SELECT id, matn, bajarildi FROM vazifalar
WHERE egasi_id = 1 AND matn LIKE '%#o''qish%';

Natija:

text
 id |                       matn                       | bajarildi 
----+--------------------------------------------------+-----------
  1 | JavaScript kursining 26-qismini boshlash #o'qish | f
  2 | Postgres'ni Docker'da ko'tarish #o'qish #docker  | t
 34 | SQL JOIN mashqlarini yechish #o'qish             | f
(3 rows)

3 ta qator. Bu son yodda qolsin.

2–3-qadam — tranzaksiyada o'zgartirish. SELECT ni UPDATE ga aylantiramiz, WHERE ni o'zgartirmasdan nusxa olamiz:

sql
BEGIN;
UPDATE vazifalar SET bajarildi = true
WHERE egasi_id = 1 AND matn LIKE '%#o''qish%'
RETURNING id, bajarildi;

Natija:

text
BEGIN
 id | bajarildi 
----+-----------
  1 | t
  2 | t
 34 | t
(3 rows)

UPDATE 3

4-qadam — qaror. UPDATE 3 — SELECT dagi 3 ga teng, qatorlar o'sha. Kutilgandek bo'lsa — COMMIT;. Son boshqacha bo'lsa (masalan UPDATE 40) — ROLLBACK; va hech narsa o'zgarmaydi. Kanon bu darsda ROLLBACK qildi — baza o'z holida qolishi uchun.

Tranzaksiya (transaction) — BEGIN dan COMMIT gacha bo'lgan buyruqlar guruhi: ular yo hammasi birga saqlanadi, yo hammasi birga bekor bo'ladi. COMMIT dan oldin o'zgarishlarni faqat siz ko'rasiz, boshqa ulanishlar — eski holatni. To'liq nazariyasi — Tranzaksiya asoslari.

4.2 WHERE unutilsa

Endi hikoyadagi xatoni ataylab qilamiz, lekin tranzaksiya ichida. Biz ishga tushirdik (PG 17.6):

sql
BEGIN;
UPDATE vazifalar SET bajarildi = false;
SELECT count(*) AS bajarilganlar FROM vazifalar WHERE bajarildi;
ROLLBACK;
SELECT count(*) AS bajarilganlar FROM vazifalar WHERE bajarildi;

Natija:

text
BEGIN
UPDATE 40
 bajarilganlar 
---------------
             0
(1 row)

ROLLBACK
 bajarilganlar 
---------------
            20
(1 row)

UPDATE 40 — hamma qator. Tranzaksiya ichida 20 ta bajarilgan vazifa yo'qoldi. ROLLBACK dan keyin — 20 tasi joyida. Tranzaksiyasiz yozilgan bo'lsa, ularni faqat zaxiradan (backup) tiklash mumkin edi — agar zaxira bo'lsa.

UPDATE N dagi N — eng birinchi tekshiruvingiz. 1 ta qatorni o'zgartirmoqchi edingiz-u, 40 ko'rsatsa — to'xtang.

4.3 Xato tranzaksiyani "buzadi"

Tranzaksiya ichida bitta xato bo'lsa, qolgan buyruqlar bajarilmaydi. Biz ishga tushirdik (PG 17.6):

sql
BEGIN;
UPDATE vazifalar SET bajarildi = true WHERE id = 1;
SELECT 1/0;
UPDATE vazifalar SET bajarildi = true WHERE id = 2;
COMMIT;

Natija:

text
BEGIN
UPDATE 1
ERROR:  division by zero
ERROR:  current transaction is aborted, commands ignored until end of transaction block
ROLLBACK

Tarjimasi: "joriy tranzaksiya bekor qilingan, tranzaksiya bloki oxirigacha buyruqlar e'tiborsiz qoldiriladi". E'tibor bering: biz COMMIT yozdik, psql esa ROLLBACK deb javob berdi. Xatodan keyin COMMIT ham bekor qilishga aylanadi — birinchi UPDATE ham saqlanmadi. Bu "hammasi yoki hech biri" qoidasi amalda.

Maslahat: psql'da \set AUTOCOMMIT off yozsangiz, har buyruq avtomatik tranzaksiyada boshlanadi va siz COMMIT yozmaguningizcha saqlanmaydi. Production bazaga qo'lda ulanadigan ba'zi jamoalar shu sozlamani .psqlrc ga qo'yadi (psql chuqur). Ehtiyot bo'ling: unutilgan ochiq tranzaksiya qatorlarni qulflab, boshqalarni kuttirib qo'yishi mumkin (Qulflar).

Tekshirib ko'ring: Tranzaksiya ichida UPDATE qildingiz va COMMIT dan oldin boshqa terminaldan SELECT qildingiz. Ikkinchi terminal nimani ko'radi?

Javob

Eski qiymatni. COMMIT qilinmagan o'zgarish faqat shu tranzaksiyaga ko'rinadi:

Qadam A terminal B terminal B ko'radigan bajarildi (id 29)
1 BEGIN; — t
2 UPDATE … SET bajarildi = false WHERE id = 29; — —
3 — SELECT bajarildi … WHERE id = 29; t (eski)
4 COMMIT; — —
5 — xuddi shu SELECT f (yangi)

Bu jadval PostgreSQL'ning sukut izolyatsiya darajasidagi (READ COMMITTED) xatti-harakati — hujjatga ko'ra; ikki terminalli tajribani Read phenomena va izolyatsiya darajalari darsida o'zimiz o'tkazamiz. Shuning uchun tranzaksiya ichida bemalol tekshirsangiz bo'ladi — foydalanuvchilar yarim tayyor holatni ko'rmaydi.

5. Boshqa jadvalga qarab o'zgartirish

5.1 UPDATE … FROM

Savol: "Bekzodning hamma bajarilmagan vazifalarini bajarilgan qil". Bizda email bor (bekzod@example.com), vazifalar da esa faqat egasi_id. Ikki jadvalni bitta buyruqda bog'lash kerak. PostgreSQL'da buning uchun UPDATE … FROM. Kanon (PostgreSQL 18.6, ROLLBACK bilan):

sql
BEGIN;
UPDATE vazifalar v
SET bajarildi = true
FROM foydalanuvchilar f
WHERE f.id = v.egasi_id
  AND f.email = 'bekzod@example.com'
  AND NOT v.bajarildi
RETURNING v.id, v.matn;
ROLLBACK;

Natija:

text
BEGIN
 id |             matn              
----+-------------------------------
 19 | Universitet kontrakti #to'lov
 33 | Noutbukka SSD qo'yish #ta'mir
(2 rows)

UPDATE 2
ROLLBACK

O'qilishi:

  • vazifalar v, foydalanuvchilar f — jadvallarga qisqa nom (v, f). Endi v.bajarildi — "vazifalardagi bajarildi".
  • FROM foydalanuvchilar f — o'zgartirishda qo'shimcha jadval ishtirok etadi.
  • WHERE f.id = v.egasi_id — bog'lash sharti: har vazifani o'z egasi bilan juftlaydi. Bu eng muhim qator.
  • Qolgan shartlar — kerakli juftliklarni tanlaydi.

Diqqat: Bog'lash shartini (f.id = v.egasi_id) unutsangiz, har vazifa har foydalanuvchi bilan juftlanadi. Bekzod qatori bor ekan, hamma vazifalar shartga mos keladi — butun jadval o'zgaradi. WHERE siz UPDATE ning yashirin ko'rinishi. Tekshiruv usuli o'sha: avval xuddi shu FROM … WHERE bilan SELECT.

Bu ikki jadvalni bog'lash g'oyasi — JOIN'lar darsining mavzusi. UPDATE … FROM — PostgreSQL kengaytmasi; MySQL'da UPDATE … JOIN deb yoziladi.

5.2 DELETE … USING

DELETE da xuddi shu g'oya USING deb ataladi. Kanon (PostgreSQL 18.6, ROLLBACK bilan) — Gulnoraning bajarilgan vazifalari:

sql
BEGIN;
DELETE FROM vazifalar v
USING foydalanuvchilar f
WHERE f.id = v.egasi_id
  AND f.email = 'gulnora@example.com'
  AND v.bajarildi
RETURNING v.id, v.matn;
ROLLBACK;

Natija:

text
BEGIN
 id |                  matn                   
----+-----------------------------------------
  4 | Somsa uchun xamir tayyorlash #oshxona
 22 | Un va yog' xarid qilish #bozor #oshxona
(2 rows)

DELETE 2
ROLLBACK

Nega FROM emas, USING? DELETE FROM da FROM so'zi band — u o'chiriladigan jadvalni bildiradi. Ikkinchi jadval uchun boshqa so'z kerak bo'lgan.

PostgreSQL 18 da RETURNING ga old. va new. qo'shildi: UPDATE … RETURNING old.matn, new.matn bitta so'rovda "nima edi — nima bo'ldi" ni beradi. Mashinadagi 17.6 da bu yo'q, biz sinamadik — hujjat bo'yicha (postgresql.org/docs/18, UPDATE, 2026-10-24).

6. TRUNCATE: jadvalni bo'shatish

6.1 TRUNCATE va DELETE farqi

TRUNCATE jadval — butun jadvalni bir zumda bo'shatadi. Kanon (PostgreSQL 18.6, ROLLBACK bilan):

sql
BEGIN;
TRUNCATE vazifalar;
SELECT count(*) FROM vazifalar;
ROLLBACK;
SELECT count(*) AS hammasi_joyida FROM vazifalar;

Natija:

text
BEGIN
TRUNCATE TABLE
 count 
-------
     0
(1 row)

ROLLBACK
 hammasi_joyida 
----------------
             40
(1 row)

PostgreSQL'da TRUNCATE ham tranzaksiyali — ROLLBACK uni qaytardi. (MySQL'da va boshqa ba'zi bazalarda bunday emas.)

DELETE FROM t TRUNCATE t
WHERE bor yo'q — faqat hammasi
RETURNING bor yo'q
Tezlik katta jadvalda sekin (har qator alohida) juda tez (fayl almashtiriladi)
Qator trigger'lari ishlaydi ishlamaydi
Qulf qatorlarga butun jadvalga (o'qish ham kutadi)
ID hisoblagichi o'zgarmaydi RESTART IDENTITY bilan noldan

Biz ishga tushirdik (PG 17.6, ROLLBACK bilan) — RESTART IDENTITY:

sql
BEGIN;
TRUNCATE vazifalar RESTART IDENTITY;
INSERT INTO vazifalar (egasi_id, matn)
VALUES (1, 'Yangi boshlanish') RETURNING id;
ROLLBACK;

Natija:

text
BEGIN
TRUNCATE TABLE
 id 
----
  1
(1 row)

INSERT 0 1
ROLLBACK

Yangi vazifa yana 1-raqamni oldi. Sinov bazasini tozalash uchun qulay. Production'da TRUNCATE — deyarli hech qachon kerak emas.

6.2 Tashqi kalit TRUNCATE'ni to'xtatadi

Kanon (PostgreSQL 18.6):

sql
TRUNCATE foydalanuvchilar;

Natija:

text
ERROR:  cannot truncate a table referenced in a foreign key constraint
DETAIL:  Table "vazifalar" references "foydalanuvchilar".
HINT:  Truncate table "vazifalar" at the same time, or use TRUNCATE ... CASCADE.

Tarjimasi: "tashqi kalit ishora qilayotgan jadvalni bo'shatib bo'lmaydi. Vazifalar foydalanuvchilarga ishora qiladi. Maslahat: vazifalarni ham birga bo'shating yoki TRUNCATE … CASCADE ishlating".

TRUNCATE qatorma-qator ishlamaydi, shuning uchun ON DELETE CASCADE ni bajara olmaydi. U shunchaki rad etadi. TRUNCATE … CASCADE esa bog'langan hamma jadvallarni bo'shatadi — uni faqat aniq bilganingizda ishlating.

7. SQL qadami: tahrir va o'chirish so'rovlari (holat 15, commit yo'q)

Sxema o'zgarmaydi. 25-qism dagi PATCH /vazifalar/:id va DELETE /vazifalar/:id bazada shunday ko'rinadi:

sql
-- PATCH: faqat o'z vazifasini, yangi holatni qaytarib
UPDATE vazifalar
SET bajarildi = true
WHERE id = 34 AND egasi_id = 1
RETURNING id, matn, bajarildi;

-- DELETE: faqat o'z vazifasini
DELETE FROM vazifalar
WHERE id = 34 AND egasi_id = 1
RETURNING id;

AND egasi_id = 1 ga qarang. Bu — resurs egaligi tekshiruvi. Usiz Aziz id ni o'zgartirib, Dilnozaning vazifasini o'chira olardi. Ikkala shart bitta WHERE da — alohida "avval o'qib tekshir, keyin o'chir" kerak emas. RETURNING bo'sh qaytsa (DELETE 0), ilova 404 beradi: "bunday vazifa yo'q" — va begona vazifa bormi-yo'qmi, oshkor qilinmaydi. Haqiqiy egasi_id autentifikatsiyadan keladi (28-qism); ungacha biz uni qo'lda yozamiz. Repository kodi — Parametrli so'rovlar darsida.

8. Ko'p uchraydigan xatolar

Xato yoki belgi Sabab Davosi
UPDATE 40 (1 ta kutilgan) WHERE unutilgan BEGIN ichida; ROLLBACK
UPDATE … FROM butun jadvalni o'zgartirdi Bog'lash sharti yo'q WHERE f.id = v.egasi_id
UPDATE 0 Shartga mos qator yo'q Xato emas — ilovada 404
current transaction is aborted … Tranzaksiyada oldinroq xato bo'lgan ROLLBACK va qaytadan
COMMIT dan keyin ROLLBACK chiqdi Tranzaksiyada xato bo'lgan Xatoni tuzatib qayta bajaring
cannot truncate a table referenced in a foreign key constraint Boshqa jadval ishora qiladi Ikkalasini birga yoki DELETE
DELETE 1, lekin ko'p narsa yo'qoldi ON DELETE CASCADE O'chirishdan oldin bog'lanishlarni tekshiring

9. Mashqlar

1-mashq (oson): natijani toping

Holat 15 (40 vazifa, 20 tasi bajarilgan).

  • UPDATE vazifalar SET bajarildi = true WHERE id = 500 holat qatori: UPDATE
  • BEGIN; DELETE FROM vazifalar; ROLLBACK; dan keyin vazifalar soni:
  • UPDATE t SET a = b, b = a dan keyin a ning qiymati — eski
  • Jadvalni bo'shatib, ID'ni ham 1 dan boshlash: TRUNCATE vazifalar
Yechim
  • 0 — mos qator yo'q, xato emas.
  • 40 — ROLLBACK hammasini qaytardi.
  • b — SET ifodalari o'zgarishdan oldingi qatorni ko'radi, shuning uchun ikkalasi almashadi.
  • RESTART IDENTITY — sinov bazalari uchun.

2-mashq (o'rta): Sardorning mashinasi

Sardor (sardor@example.com) mashinaga oid (#mashina tegli) hamma ishni tugatdi. Xavfsiz tartibda bajaring: avval SELECT bilan ko'ring, keyin tranzaksiyada UPDATE … FROM (faqat bajarilmaganlar), RETURNING, COMMIT. Sardorning id sini qo'lda yozmang.

Yechim
sql
-- 1) avval ko'rish
SELECT v.id, v.matn, v.bajarildi
FROM vazifalar v, foydalanuvchilar f
WHERE f.id = v.egasi_id
  AND f.email = 'sardor@example.com'
  AND v.matn LIKE '%#mashina%'
ORDER BY v.id;

-- 2) tranzaksiyada o'zgartirish
BEGIN;
UPDATE vazifalar v
SET bajarildi = true
FROM foydalanuvchilar f
WHERE f.id = v.egasi_id
  AND f.email = 'sardor@example.com'
  AND v.matn LIKE '%#mashina%'
  AND NOT v.bajarildi
RETURNING v.id, v.matn, v.bajarildi;
COMMIT;

Natija (biz ishga tushirdik, PG 17.6, psql -q — holat qatorlari yashirin):

text
 id |                      matn                      | bajarildi 
----+------------------------------------------------+-----------
 10 | Mashinani texnik ko'rikka olib borish #mashina | f
 11 | Moy almashtirish #mashina                      | t
(2 rows)

 id |                      matn                      | bajarildi 
----+------------------------------------------------+-----------
 10 | Mashinani texnik ko'rikka olib borish #mashina | t
(1 row)

SELECT 2 qator ko'rsatdi, UPDATE — 1 qator. Bu xato emas: AND NOT v.bajarildi allaqachon bajarilganini (11) o'tkazib yubordi. Farqni oldindan tushunib, keyin COMMIT qilish — aynan xavfsiz tartibning maqsadi. SELECT dagi FROM vazifalar v, foydalanuvchilar f — INSERT va RETURNING darsining 3-mashqidagi juftlash usuli.

3-mashq (qiyin): Bekzodning bajarilganlari

Bekzod (bekzod@example.com) bajarilgan vazifalarini tozalamoqchi. Bitta tranzaksiyada: DELETE … USING bilan o'chiring va o'chirilganlarni ko'rsating, so'ng Bekzodning qolgan vazifalarini (egasi_id 7) chiqarib, faqat bajarilmaganlar qolganini tekshiring, keyin COMMIT.

Yechim
sql
BEGIN;
DELETE FROM vazifalar v
USING foydalanuvchilar f
WHERE f.id = v.egasi_id
  AND f.email = 'bekzod@example.com'
  AND v.bajarildi
RETURNING v.id, v.matn;

-- tekshiruv: Bekzodda faqat bajarilmaganlar qoldimi?
SELECT id, matn, bajarildi
FROM vazifalar
WHERE egasi_id = 7
ORDER BY id;
COMMIT;

Natija (biz ishga tushirdik, PG 17.6, psql -q):

text
 id |               matn               
----+----------------------------------
 25 | Algoritmlar: 5 ta masala #o'qish
 39 | Do'stlar bilan choyxona #dam
(2 rows)

 id |             matn              | bajarildi 
----+-------------------------------+-----------
 19 | Universitet kontrakti #to'lov | f
 33 | Noutbukka SSD qo'yish #ta'mir | f
(2 rows)

Bekzodda 4 ta vazifa bor edi: 2 tasi o'chdi, 2 tasi (bajarilmagan) qoldi. Tekshiruv COMMIT dan oldin, tranzaksiya ichida — natija noto'g'ri bo'lsa, COMMIT o'rniga ROLLBACK yozasiz.

10. Real ishda

  • Ilova kodi — UPDATE … WHERE id = $1 AND egasi_id = $2 RETURNING … — tahrir va o'chirishning standart shakli; rowCount = 0 → 404.
  • Qo'lda tuzatish (hotfix) — production bazada qo'lda SQL yozish kerak bo'lsa, tajribali jamoalarda qoida: ikkinchi odam ko'rib chiqadi, BEGIN ichida, RETURNING bilan, oldin zaxira. Ba'zi kompaniyalarda production'ga to'g'ridan-to'g'ri yozish umuman taqiqlangan — faqat migratsiya fayllari orqali.
  • "O'chirish" ko'pincha UPDATE — foydalanuvchi "o'chirdim" degan vazifa aslida ochirilgan_vaqt ustuni bilan yashiriladi (yumshoq o'chirish, "Savat"). Buni Soft delete, timestamps va tarix darsida quramiz.
  • Intervyu savollari: "DELETE va TRUNCATE farqi?", "WHERE siz UPDATE ni qanday oldini olasiz?", "UPDATE boshqa jadval ma'lumotiga qarab qanday yoziladi?".

Xulosa

  • UPDATE t SET a = …, b = … WHERE … va DELETE FROM t WHERE …; SET ifodalari eski qatorni ko'radi.
  • Xavfsiz tartib: avval SELECT (son), BEGIN, o'zgartirish + RETURNING, son mos bo'lsa COMMIT, aks holda ROLLBACK.
  • UPDATE 0 — xato emas (ilovada 404); cheklovlar UPDATE ni ham tekshiradi; tranzaksiyadagi xato COMMIT ni ROLLBACK ga aylantiradi.
  • UPDATE … FROM va DELETE … USING — boshqa jadvalga qarab; bog'lash shartini unutmang.
  • DELETE + CASCADE jim zanjir; TRUNCATE — tez, WHERE siz, tashqi kalit bilan bog'langan jadvalda rad etiladi.
  • Ilovada egalik tekshiruvi WHERE id = … AND egasi_id = … bilan bitta so'rovda.

Keyingi dars: NULL mantiqi — NULL nega "noma'lum", uch qiymatli mantiq, IS DISTINCT FROM, COALESCE va NOT IN ning mashhur tuzog'i.

Manbalar

  • PostgreSQL 18 hujjati — UPDATE (FROM, RETURNING old/new)
  • PostgreSQL 18 hujjati — DELETE (USING)
  • PostgreSQL 18 hujjati — TRUNCATE (RESTART IDENTITY, CASCADE, MVCC-xavfsiz emasligi)
  • PostgreSQL 18 hujjati — psql: AUTOCOMMIT
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
SQL UPDATE va DELETE: ma'lumotni xavfsiz o'zgartirish va o'chirish — IlmHamroh