آموزش #SQL ‌ ⚡️ می‌دونستین با ON CONFLICT می‌شه توی یک دستور گفت «اگه…

#آموزش #SQL
‌
⚡️ می‌دونستین با ON CONFLICT می‌شه توی یک دستور گفت «اگه ردیف بود آپدیتش کن، نبود اضافه‌اش کن»؟
‌
به این کار 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

‌
⚠️ بدون ON CONFLICT چی می‌شه؟
اگه یک 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
👍3
۱۶ آبان ۱۴۰۵ ۱۵۵