به این کار upsert میگن. فرض کنید جدول stock با ستونهای product (کلید اصلی) و qty داریم و الان pen با موجودی 10 و book با موجودی 3 توشه. حالا پنج تا pen دیگه رسیده:
INSERT INTO stock (product, qty) VALUES ('pen', 5)
ON CONFLICT (product)
DO UPDATE SET qty = stock.qty + excluded.qty;
SELECT * FROM stock ORDER BY product;
خروجی (توی SQLite):
product qty
------- ---
book 3
pen 15
چون pen از قبل بود، INSERT به خطا نخورد و بهجاش موجودی 10 با 5 جمع شد. عبارت
excluded.qty یعنی مقداری که میخواستیم اضافه کنیم (اینجا 5) و stock.qty مقدار فعلی ردیفه.
همین دستور برای محصول جدید (bag) یک ردیف تازه میسازه:
INSERT INTO stock (product, qty) VALUES ('bag', 7)
ON CONFLICT (product)
DO UPDATE SET qty = stock.qty + excluded.qty;
SELECT * FROM stock ORDER BY product;
خروجی:
product qty
------- ---
bag 7
book 3
pen 10
اگه یک INSERT معمولی (بدون ON CONFLICT) برای pen اجرا کنید، چون product کلید اصلیه، خطای UNIQUE constraint failed: stock.product میگیرید و هیچ تغییری انجام نمیشه.
یک نکتهٔ مهم: ON CONFLICT فقط روی ستونی کار میکنه که PRIMARY KEY یا UNIQUE باشه؛ وگرنه SQLite خطای ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint میده.
💎 جایگزین کردن یا نادیده گرفتن
اگه بهجای جمع، مقدار جدید باید جایگزین بشه، فقط
qty = excluded.qty بنویسید:
INSERT INTO stock (product, qty) VALUES ('pen', 5)
ON CONFLICT (product)
DO UPDATE SET qty = excluded.qty;
SELECT * FROM stock ORDER BY product;
خروجی:
product qty
------- ---
book 3
pen 5
و اگه میخواید ردیف تکراری بیسروصدا نادیده گرفته بشه، از DO NOTHING استفاده کنید:
INSERT INTO stock (product, qty) VALUES ('book', 99)
ON CONFLICT (product) DO NOTHING;
SELECT * FROM stock ORDER BY product;
خروجی:
product qty
------- ---
book 3
pen 10
موجودی book همون 3 موند و 99 نادیده گرفته شد.
▫️ طبق مستندات SQLite، این سینتکس از PostgreSQL گرفته شده و همین دستورها اونجا هم کار میکنن. توی MySQL معادلش ON DUPLICATE KEY UPDATE هست.
▫️ توی PostgreSQL برای اشاره به مقدار فعلی ردیف، باید اسم جدول رو بنویسید (stock.qty، نه فقط qty)؛ برای همین توی مثالها از همین شکل استفاده کردیم.
▫️ برای امتحان، sqlite3 رو با نمایش جدولی باز کنید:
sqlite3 -header -column test.db
بعد جدول نمونه رو بسازید و هر کوئری رو روی جدول تازه اجرا کنید:
CREATE TABLE stock (product TEXT PRIMARY KEY, qty INTEGER);
INSERT INTO stock VALUES ('pen', 10), ('book', 3);
آموزش هوش مصنوعی و برنامه نویسی 👇
@codingyar
وبسایت آموزشی:
www.codingyar.com
