UPSERT dan MERGE di SQL: Insert atau Update Sekaligus (2026)
TL;DR
UPSERT adalah operasi SQL yang nge-insert baris baru kalau belum ada, atau nge-update kalau sudah ada, dalam satu perintah. Di PostgreSQL pakai INSERT ON CONFLICT, di MySQL pakai INSERT ON DUPLICATE KEY UPDATE, dan di SQL Server pakai MERGE. Operasi ini butuh primary key atau unique constraint buat nentuin baris mana yang duplikat.
UPSERT adalah operasi SQL yang nge-insert baris baru kalau belum ada, atau nge-update kalau udah ada, dalam satu perintah. Namanya gabungan dari update dan insert.
Tanpa ini, kamu harus cek dulu apakah data ada, baru mutusin insert atau update. Dua langkah, dan rawan bug kalau ada dua proses jalan bareng.
Aku bahas cara pakai UPSERT di tiga database populer, plus perintah MERGE yang lebih fleksibel. Semua pakai contoh data stok toko.
Apa itu UPSERT di SQL?
UPSERT adalah cara nge-insert data yang otomatis berubah jadi update kalau barisnya udah ada. Database ngecek pakai primary key atau unique constraint. Kalau nilai kuncinya nabrak yang udah ada, database nge-update, bukan bikin baris dobel. Satu perintah, dua kemungkinan hasil.
Operasi ini butuh primary key atau unique constraint yang jelas. Tanpa itu, database nggak tau baris mana yang dianggap duplikat. Dasar perintah SQL lain ada di glossary SQL.
Gimana cara UPSERT di PostgreSQL?
PostgreSQL pakai INSERT dengan klausa ON CONFLICT. Kamu sebut kolom kunci yang mungkin nabrak, lalu tentuin apa yang terjadi kalau nabrak. Biasanya DO UPDATE buat nimpa nilai lama, atau DO NOTHING buat abaikan.
INSERT INTO stok_produk (id_produk, nama, jumlah)
VALUES (101, 'Kopi Sachet', 50)
ON CONFLICT (id_produk)
DO UPDATE SET
jumlah = EXCLUDED.jumlah,
nama = EXCLUDED.nama;Kata kunci EXCLUDED nunjuk ke nilai yang tadi mau di-insert. Jadi baris di atas artinya: kalau id_produk 101 udah ada, timpa jumlah dan namanya pakai nilai baru. Kalau belum ada, insert biasa.
Mau abaikan duplikat, bukan update? Ganti jadi ON CONFLICT (id_produk) DO NOTHING. Ini berguna buat impor data yang mungkin ada baris kembar.
Gimana cara UPSERT di MySQL?
MySQL pakai INSERT dengan ON DUPLICATE KEY UPDATE. Bedanya sama PostgreSQL, MySQL nggak minta kamu sebut kolom kunci. Dia otomatis pakai primary key atau unique index yang ada di tabel.
INSERT INTO stok_produk (id_produk, nama, jumlah)
VALUES (101, 'Kopi Sachet', 50)
ON DUPLICATE KEY UPDATE
jumlah = VALUES(jumlah),
nama = VALUES(nama);Fungsi VALUES(jumlah) nunjuk ke nilai yang mau di-insert tadi, mirip EXCLUDED di PostgreSQL. Di versi MySQL baru, sintaks ini diganti pakai alias, tapi VALUES() masih jalan di kebanyakan versi.
Apa itu perintah MERGE?
MERGE adalah perintah SQL standar yang gabungin insert, update, dan delete dalam satu blok. Dia bandingin tabel target sama sumber data, lalu tentuin aksi per kondisi. SQL Server, Oracle, dan PostgreSQL 15 ke atas ndukung ini.
MERGE INTO stok_produk AS target
USING (
SELECT 101 AS id_produk, 'Kopi Sachet' AS nama, 50 AS jumlah
) AS sumber
ON target.id_produk = sumber.id_produk
WHEN MATCHED THEN
UPDATE SET target.jumlah = sumber.jumlah
WHEN NOT MATCHED THEN
INSERT (id_produk, nama, jumlah)
VALUES (sumber.id_produk, sumber.nama, sumber.jumlah);MERGE lebih bertele-tele, tapi lebih kuat. Kamu bisa tambah WHEN MATCHED THEN DELETE buat hapus baris tertentu. Buat sinkronisasi dua tabel sekaligus, MERGE lebih pas dari UPSERT biasa.
UPSERT vs MERGE, pilih yang mana?
| Aspek | UPSERT (ON CONFLICT) | MERGE |
|---|---|---|
| Sintaks | Ringkas | Panjang |
| Aksi | Insert atau update | Insert, update, delete |
| Dukungan | PostgreSQL, MySQL | SQL Server, Oracle, PostgreSQL 15+ |
| Cocok buat | Isi ulang satu baris | Sinkron dua tabel |
Aturan pegangan: buat kasus sehari-hari kayak update stok satu produk, pakai UPSERT karena lebih pendek. Buat sinkronisasi tabel besar dengan banyak aturan, pakai MERGE.
Contoh kasus: update stok toko_berkah
Toko_berkah terima kiriman barang tiap pagi. Data kiriman masuk sebagai file, isinya id_produk dan jumlah tambahan. Sebagian produk udah ada di tabel stok, sebagian barang baru.
Tanpa UPSERT, tim harus cek satu-satu apakah produk udah ada. Dari 240 baris kiriman harian, sekitar 30 produk baru dan 210 produk lama. Ngecek manual berarti 240 query terpisah tiap pagi.
-- update stok, sekaligus tambah jumlah lama
INSERT INTO stok_produk (id_produk, nama, jumlah)
VALUES (205, 'Gula Pasir 1kg', 40)
ON CONFLICT (id_produk)
DO UPDATE SET
jumlah = stok_produk.jumlah + EXCLUDED.jumlah;Perhatiin bedanya. Di sini aku pakai stok_produk.jumlah + EXCLUDED.jumlah, bukan cuma nimpa. Jadi stok lama ditambah jumlah kiriman baru, bukan diganti. Satu perintah beresin 240 baris tadi tanpa cek manual.
Konsep gabungin dua sumber data ini mirip JOIN, yang di Python versinya ada di pandas merge.
Kesalahan umum pakai UPSERT dan MERGE
- Lupa unique constraint. Tanpa primary key atau unique index, ON CONFLICT nggak punya acuan dan error. Pastiin kolom kunci udah di-set.
- Nimpa padahal mau nambah. DO UPDATE SET jumlah = EXCLUDED.jumlah itu nimpa. Kalau mau akumulasi, tulis jumlah lama plus yang baru.
- MERGE di data yang berubah bareng. MERGE punya celah race condition di beberapa database. Buat proses paralel, UPSERT sering lebih aman.
- Asal salin sintaks antar database. ON CONFLICT nggak jalan di MySQL, ON DUPLICATE KEY nggak jalan di PostgreSQL. Cek dialek database kamu dulu.
FAQ
Apa beda UPSERT dan REPLACE di MySQL?
REPLACE di MySQL sebenernya nghapus baris lama lalu insert baru, jadi semua kolom yang nggak kamu sebut balik ke default. ON DUPLICATE KEY UPDATE cuma ngubah kolom yang kamu tentuin, sisanya tetap. Buat kebanyakan kasus, ON DUPLICATE KEY UPDATE lebih aman karena nggak diam-diam ngereset kolom lain. Hindari REPLACE kalau tabelnya punya banyak kolom.
Apakah UPSERT lebih cepat dari cek dulu baru insert?
Iya, biasanya lebih cepat dan lebih aman. Cek dulu baru insert butuh dua kali jalan ke database dan punya celah waktu di antaranya. Kalau ada dua proses jalan bareng, dua-duanya bisa lolos cek lalu bikin baris dobel. UPSERT nge-handle ini dalam satu operasi yang atomik, jadi nggak ada celah race condition.
Bisa UPSERT banyak baris sekaligus?
Bisa. Di PostgreSQL dan MySQL, kamu tinggal tulis banyak baris di bagian VALUES, lalu ON CONFLICT atau ON DUPLICATE KEY tetap satu. Ini jauh lebih cepat dari jalanin satu per satu, apalagi buat impor ribuan baris. Pastiin semua baris punya nilai kolom kunci yang valid biar database bisa deteksi duplikatnya.
Kapan sebaiknya pakai MERGE, bukan UPSERT?
Pakai MERGE kalau kamu perlu sinkronin dua tabel penuh, termasuk hapus baris yang udah nggak ada di sumber. MERGE bisa insert, update, dan delete dalam satu perintah. UPSERT cuma insert atau update. Buat kasus data warehouse yang narik tabel dari sumber tiap malam, MERGE lebih pas karena satu perintah beresin semua perubahan.
Lanjut praktek
Tiga hal yang perlu nempel: UPSERT butuh kolom kunci unik, ON CONFLICT buat PostgreSQL dan ON DUPLICATE KEY buat MySQL, dan MERGE buat kasus sinkron yang lebih rumit.
Perintah kayak gini sering muncul di tes teknis. Latihan soal yang sering keluar ada di 50 pertanyaan interview SQL.
Sintaks resmi PostgreSQL ada di dokumentasi PostgreSQL INSERT. Mau latihan nulis query langsung di browser? Cek materi SQL di Ngulik Data dan mulai ngulik query sendiri.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel terkait
Fungsi NTH_VALUE di SQL untuk Ambil Nilai ke-N (2026)
NTH_VALUE ngambil nilai baris ke-N dalam window, tapi frame default-nya sering bikin hasil NULL. Ini sintaksnya, cara benerin frame, plus contoh transaksi toko.
Running Max dan Min dengan Window Function SQL
Lacak nilai tertinggi dan terendah berjalan di SQL pakai window function MAX dan MIN OVER. Ini sintaks, frame clause, dan contoh rekor omzet toko.
Analisa Afinitas Produk (Cross-Sell) dengan SQL
Produk apa yang sering dibeli bareng? Analisa afinitas produk pakai SQL self JOIN jawab itu. Ini cara hitung support, confidence, dan lift buat strategi cross-sell.