Soal 1Pada INSERT INTO stock(sku, qty) VALUES ('A001', 15) ON CONFLICT(sku) DO UPDATE SET qty = qty + excluded.qty;, dengan A001 sudah ada (qty 120), berapa qty setelah UPSERT?
UPSERT (ON CONFLICT) dan Aplikasi Bulk INSERT
Artikel ini adalah bagian dari Kursus SQL, yang membantu Anda menguasai keterampilan SQL praktis dari nol, mulai dari dasar hingga kueri kompleks dan penyetelan SQL.
Pakai INSERT … ON CONFLICT(sku) DO UPDATE pada tabel stock untuk menambahkan excluded.qty ke A001 yang sudah ada, memasukkan A006 baru, melindungi baris lama dengan DO NOTHING, dan melakukan bulk UPSERT 3 baris dari stock_in — semuanya dipraktikkan langsung.
Data yang akan kita pakai — stock dan stock_in
UPSERT (perpaduan UPDATE dan INSERT —
operasi "update kalau ada, insert kalau tidak" dalam satu pernyataan) diimplementasikan lewat sintaks INSERT … ON CONFLICT(key) DO UPDATE.
Kalau baris bentrok dengan primary key atau batasan UNIQUE, update dijalankan; kalau tidak, baris itu langsung di-insert apa adanya.
ON CONFLICT DO UPDATE — update kalau ada, insert kalau tidak
Menulis INSERT INTO table(...) VALUES (...) ON CONFLICT(key_col) DO UPDATE SET col = ... berarti: kalau baris yang akan kamu insert bentrok dengan kunci yang dideklarasikan di ON CONFLICT (primary key atau kolom UNIQUE), update DO UPDATE dijalankan; kalau tidak ada bentrokan, baris itu langsung di-insert.
Di dalam DO UPDATE, nama tabel khusus excluded memungkinkan kamu merujuk "nilai dari baris yang akan kamu insert".
Tulis qty = qty + excluded.qty dan, ketika bentrok, qty yang ada akan bertambah sebesar qty yang ingin kamu insert.
Pakai qty = excluded.qty untuk timpa dan qty = qty + excluded.qty untuk akumulasi, tergantung kebutuhan.
-- Bentrok dengan sku yang ada → DO UPDATE menambah qty
INSERT INTO stock(sku, name, qty, price)
VALUES ('A001', 'Pen', 5, 80)
ON CONFLICT(sku) DO UPDATE SET qty = qty + excluded.qty;
-- sku baru → tidak bentrok, hanya di-insert
INSERT INTO stock(sku, name, qty, price)
VALUES ('A006', 'Marker', 3, 120)
ON CONFLICT(sku) DO UPDATE SET qty = qty + excluded.qty;
SELECT sku, name, qty FROM stock WHERE sku IN ('A001', 'A006');
DO NOTHING — tidak melakukan apa-apa ketika bentrok
Kalau kamu tidak ingin memperbarui maupun memasukkan — yaitu, "diam-diam lewatkan ketika bentrok" — gunakan ON CONFLICT(key) DO NOTHING.
Tanpa bentrokan baris di-insert; ketika bentrok baris diabaikan tanpa error.
Pada contoh di bawah, mencoba memasukkan A002 yang sudah ada dengan DO NOTHING akan bentrok dan diabaikan, sementara A007 yang baru akan di-insert.
-- Abaikan ketika bentrok (DO NOTHING)
INSERT INTO stock(sku, name, qty, price)
VALUES ('A002', 'Note', 999, 999)
ON CONFLICT(sku) DO NOTHING;
-- A002 mempertahankan nilai aslinya (qty 60 / price 250)
SELECT sku, name, qty, price FROM stock WHERE sku = 'A002';
UPSERT banyak baris — gabungkan bulk INSERT dengan ON CONFLICT
Ketika kamu menambahkan ON CONFLICT pada INSERT banyak baris — VALUES (...),(...),(...) dipisahkan koma — setiap baris secara independen "update kalau bentrok, insert kalau tidak".
Kamu bisa merefleksikan data kedatangan dalam satu pernyataan, menggantikan loop prosedural yang mencabang antara UPDATE dan INSERT per baris dengan satu SQL.
Bahkan di UPSERT banyak baris, excluded tetap berarti "nilai yang akan kamu insert untuk baris ini," jadi menulis qty = qty + excluded.qty menerapkan "tambahkan untuk baris yang ada, insert apa adanya untuk baris baru" per baris.
Latihan terakhir artikel ini adalah bulk UPSERT semua 3 baris stock_in (A001 / A004 / A006).
-- UPSERT banyak baris: baris yang ada mengakumulasi qty dan menyegarkan price; baris baru di-insert
INSERT INTO stock(sku, name, qty, price)
VALUES
('A002', 'Note', 10, 260),
('A005', 'Glue', 20, 190),
('A007', 'Ruler', 15, 90)
ON CONFLICT(sku) DO UPDATE
SET qty = qty + excluded.qty,
price = excluded.price;
SELECT sku, name, qty, price FROM stock ORDER BY sku;
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Apa yang dirujuk excluded di dalam DO UPDATE UPSERT?
Soal 3Sintaks mana yang kamu pakai supaya tidak pernah memodifikasi data yang ada dan diam-diam mengabaikan bentrokan tanpa error?