5-bo‘lim

RETURNING va upsert

Ko'p qatorli INSERT, RETURNING bilan natijani darhol olish, UPDATE ... FROM, DELETE ... USING va ON CONFLICT bilan upsert.

🕑 11 daqiqa o‘qish 📄 617 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. RETURNING - natijani darhol olish
  2. ON CONFLICT - upsert
  3. UPDATE ... FROM
  4. DELETE ... USING
  5. Xulosa

INSERT, UPDATE va DELETE ni siz bilasiz. Bu bo'limda PostgreSQL ularga qo'shgan ikkita narsani ko'ramiz - va ikkalasi ham kundalik ishni sezilarli soddalashtiradi.

SQL
CREATE TABLE oquvchi (
    id      int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    ism     text NOT NULL,
    email   text UNIQUE NOT NULL,
    ball    int NOT NULL DEFAULT 0,
    faol    boolean NOT NULL DEFAULT true
);

INSERT INTO oquvchi (ism, email, ball) VALUES
    ('Husanboy', '[email protected]', 85),
    ('Malika',   '[email protected]',   92),
    ('Nodira',   '[email protected]',   78),
    ('Aziza',    '[email protected]',    64);

RETURNING - natijani darhol olish #

Odatdagi INSERT hech narsa qaytarmaydi. Yangi qatorning id sini bilish uchun ikkinchi so'rov yuborish kerak bo'lardi.

PostgreSQL da esa:

SQL
INSERT INTO oquvchi (ism, email, ball)
VALUES ('Kamola', '[email protected]', 88)
RETURNING id, ism, ball;
Natija
 id |  ism   | ball
----+--------+------
  5 | Kamola |   88
(1 row)

INSERT 0 1

Bitta so'rov - va yangi id qo'lingizda.

RETURNING nima uchun muhim

Usiz ikkita so'rov kerak bo'ladi: avval INSERT, keyin SELECT.

Bu shunchaki sekinlik emas - bu poyga holati. Ikki so'rov orasida boshqa ulanish ham qator qo'shishi mumkin va siz noto'g'ri id ni olasiz.

RETURNING esa bitta amal ichida ishlaydi, shuning uchun bunday xato umuman paydo bo'lmaydi.

U UPDATE va DELETE bilan ham ishlaydi - o'chirilgan qatorni jurnalga yozish uchun juda qulay.

RETURNING o'chirishda ayniqsa foydali - nima o'chganini ko'rasiz:

SQL
DELETE FROM oquvchi WHERE ball < 70
RETURNING id, ism, ball;
Natija
 id |  ism  | ball
----+-------+------
  4 | Aziza |   64
(1 row)

DELETE 1

UPDATE da esa eski va yangi qiymatni solishtirish mumkin:

SQL
UPDATE oquvchi SET ball = ball + 5 WHERE ism = 'Nodira'
RETURNING ism, ball - 5 AS eski_ball, ball AS yangi_ball;
Natija
  ism   | eski_ball | yangi_ball
--------+-----------+------------
 Nodira |        78 |         83
(1 row)

UPDATE 1

ON CONFLICT - upsert #

Klassik vazifa: "qator bo'lsa yangila, bo'lmasa qo'sh".

Oddiy yo'l bilan bu uch qadam bo'lardi: tekshir, keyin qo'sh yoki yangila. Va yana poyga holati paydo bo'ladi.

Bitta so'rov, ikki xil natija INSERT ... ON CONFLICT bunday qator bormi? YO'Q yangi qator qo'shiladi HA mavjud qator yangilanadi Nima uchun "avval tekshir, keyin yoz" ishlamaydi Siz tekshirdingiz - qator yo'q. Shu lahzada boshqa ulanish o'sha qatorni qo'shdi. Sizning INSERT ingiz endi UNIQUE cheklovga urilib xato beradi. ON CONFLICT bu holatni bitta atomar amalda hal qiladi
Bu xato kam yuklamada ko'rinmaydi - u aynan eng band paytda chiqadi

PostgreSQL da bu bitta so'rov:

SQL
INSERT INTO oquvchi (ism, email, ball)
VALUES ('Malika', '[email protected]', 99)
ON CONFLICT (email) DO UPDATE SET ball = EXCLUDED.ball
RETURNING id, ism, ball;
Natija
 id |  ism   | ball
----+--------+------
  2 | Malika |   99
(1 row)

INSERT 0 1

EXCLUDED - bu qo'shilmoqchi bo'lgan, lekin to'qnashuv sababli qabul qilinmagan qator. Ya'ni "yangi qiymatni ol".

Yangi email bilan esa oddiy qo'shish bo'ladi:

SQL
INSERT INTO oquvchi (ism, email, ball)
VALUES ('Dilnoza', '[email protected]', 71)
ON CONFLICT (email) DO UPDATE SET ball = EXCLUDED.ball
RETURNING id, ism, ball;
Natija
 id |   ism   | ball
----+---------+------
  5 | Dilnoza |   71
(1 row)

INSERT 0 1

Bir xil so'rov ikki xil ish bajardi - va ikkalasida ham natija darhol qaytdi.

DO NOTHING - jimgina o'tkazib yuborish

Ba'zan to'qnashuvda hech narsa qilish kerak emas - shunchaki o'tkazib yuborish kifoya:

SQL
INSERT INTO oquvchi (ism, email) VALUES ('Yangi', '[email protected]')
ON CONFLICT DO NOTHING;

Bu "agar allaqachon bo'lsa, tinch qo'y" degani. Jurnal yozish yoki keshni to'ldirishda juda qulay.

Diqqat: DO NOTHING xatoni yashiradi. Qator qo'shilmagani haqida hech qanday belgi bo'lmaydi. Shuning uchun qo'shilgan qatorlar sonini bilish kerak bo'lsa, RETURNING qo'shing - o'tkazib yuborilgan qator qaytmaydi.

UPDATE ... FROM #

Bitta jadvalni boshqa jadvaldagi ma'lumot asosida yangilash kerak bo'lsa:

SQL
CREATE TABLE bonus (email text, qoshimcha int);
INSERT INTO bonus VALUES ('[email protected]', 10), ('[email protected]', 5);

UPDATE oquvchi o
SET ball = o.ball + b.qoshimcha
FROM bonus b
WHERE o.email = b.email
RETURNING o.ism, o.ball;
Natija
CREATE TABLE
INSERT 0 2
   ism    | ball
----------+------
 Husanboy |   95
 Nodira   |   83
(2 rows)

UPDATE 2

Bu JOIN ga o'xshaydi, lekin yangilash uchun. Ko'p bazalarda buni qilish ancha noqulay.

DELETE ... USING #

O'chirishda ham xuddi shunday imkoniyat bor:

SQL
CREATE TABLE qora_royxat (email text);
INSERT INTO qora_royxat VALUES ('[email protected]');

DELETE FROM oquvchi o
USING qora_royxat q
WHERE o.email = q.email
RETURNING o.ism, o.email;
Natija
CREATE TABLE
INSERT 0 1
  ism  |     email
-------+----------------
 Aziza | [email protected]
(1 row)

DELETE 1
WHERE siz UPDATE yoki DELETE - eng qimmat xato

WHERE ni unutsangiz, so'rov butun jadvalga tegadi.

Himoya usullari:

UsulQanday ishlaydi
Avval SELECT bilan sinashXuddi shu WHERE bilan nechta qator chiqishini ko'ring
Tranzaksiya ichida bajarishBEGIN ... natijani ko'rib, COMMIT yoki ROLLBACK
RETURNING qo'shishNima o'zgarganini darhol ko'rasiz

Eng ishonchlisi - ikkinchisi. 16-bo'limda tranzaksiyalarni batafsil ko'ramiz, lekin qoidani hozirdan odat qiling: ishlab chiqarish bazasida UPDATE ni har doim BEGIN bilan boshlang.

Amaliy topshiriq
  1. Yangi o'quvchi qo'shing va RETURNING bilan uning id sini oling.
  2. RETURNING * yozib ko'ring - nima farq qiladi?
  3. DELETE da RETURNING ishlating va o'chgan qatorlarni ko'ring.
  4. UPDATE da eski va yangi qiymatni bitta so'rovda chiqaring.
  5. Mavjud email bilan ON CONFLICT DO UPDATE ni sinang.
  6. Yangi email bilan xuddi shu so'rovni takrorlang.
  7. EXCLUDED nimani anglatishini o'z so'zingiz bilan yozing.
  8. DO NOTHING ni sinang va nechta qator qaytganini ko'ring.
  9. UPDATE ... FROM bilan ikkinchi jadvaldan qiymat ko'chiring.
  10. Nima uchun "tekshir, keyin yoz" xavfli ekanini tushuntiring.

Xulosa #

  • RETURNING INSERT, UPDATE va DELETE natijasini darhol qaytaradi.
  • U ikkinchi so'rovni ham, u bilan bog'liq poyga holatini ham yo'q qiladi.
  • ON CONFLICT "bo'lsa yangila, bo'lmasa qo'sh" vazifasini bitta amalda bajaradi.
  • EXCLUDED - to'qnashuv sababli qabul qilinmagan yangi qator.
  • DO NOTHING jimgina o'tkazib yuboradi - lekin belgi bermaydi.
  • UPDATE ... FROM boshqa jadvaldagi ma'lumot asosida yangilaydi.
  • DELETE ... USING xuddi shu imkoniyatni o'chirishga beradi.
  • "Avval tekshir, keyin yoz" naqshi ko'p foydalanuvchida buziladi.
  • WHERE siz UPDATE butun jadvalga tegadi - BEGIN bilan himoyalaning.
  • RETURNING ni UPDATE bilan birga ishlatish - o'zgarishni tekshirishning eng tez yo'li.

Keyingi bo'limda SELECT ning PostgreSQL ga xos kuchli tomonlarini ko'ramiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.