TL;DR
REPLACE SQL mengganti semua kemunculan sebuah substring di dalam teks dengan substring lain. Sintaksnya REPLACE(teks, cari, ganti) dan jalan di PostgreSQL, MySQL, SQL Server, maupun SQLite. Fungsi ini paling sering dipakai buat normalisasi nomor telepon, hapus tanda baca, dan seragamkan kode produk sebelum data dipakai buat JOIN.
REPLACE ganti semua kemunculan sebuah teks di dalam kolom dengan teks lain. Sintaksnya REPLACE(teks, yang_dicari, penggantinya).
Fungsi ini yang bakal kamu pakai tiap kali dapat kolom nomor HP yang formatnya beda-beda: ada yang pakai tanda hubung, ada yang pakai titik, ada yang diawali +62. Satu query, semuanya seragam.
Dan di database, data kotor bukan cuma bikin laporan jelek. Data kotor bikin JOIN gagal diam-diam.
REPLACE adalah fungsi string yang nyari sebuah substring di dalam teks, terus nukar semua kemunculannya dengan substring lain. Bukan cuma yang pertama. Semuanya sekaligus.
REPLACE(string_sumber, string_yang_dicari, string_pengganti)
Tiga bahan, semuanya wajib:
| Argumen | Isi | Contoh |
|---|---|---|
| string_sumber | Kolom atau teks yang mau dibersihin | no_hp |
| string_yang_dicari | Karakter atau kata yang mau diganti | '-' |
| string_pengganti | Penggantinya. Kosongin buat hapus | '' |
Query paling dasarnya kayak gini:
SELECT REPLACE('0812-3456-7890', '-', '') AS hp_bersih;
-- hasil: 081234567890
Kabar bagusnya, REPLACE jalan di semua database besar dengan sintaks yang sama: PostgreSQL, MySQL, SQL Server, SQLite. Nggak perlu hafal versi berbeda.
Ini kasus paling sering. Data nomor HP dari form online biasanya campur aduk formatnya.
SELECT nama,
no_hp,
REPLACE(no_hp, '-', '') AS hp_bersih
FROM pelanggan;
Masalahnya, tanda hubung bukan satu-satunya pengganggu. Ada spasi, titik, tanda kurung. Solusinya: tumpuk REPLACE-nya.
SELECT nama,
REPLACE(REPLACE(REPLACE(
no_hp, '-', ''), ' ', ''), '.', '') AS hp_bersih
FROM pelanggan;
Bacanya dari dalam ke luar. REPLACE paling dalam jalan duluan, hasilnya jadi input buat REPLACE di luarnya.
Kalau tumpukannya udah lewat 5 lapis, query-nya mulai susah dibaca. Di PostgreSQL kamu bisa pakai TRANSLATE yang lebih ringkas:
SELECT TRANSLATE(no_hp, '-. ()', '') AS hp_bersih
FROM pelanggan;
Satu baris, lima karakter kebuang sekaligus. Sayangnya TRANSLATE nggak ada di MySQL dan SQLite.
Nomor HP Indonesia punya dua format yang sama-sama valid: 08123456789 dan +628123456789. Kalau dua format ini nyampur di satu kolom, hitungan pelanggan unik kamu bakal double.
SELECT no_hp,
REPLACE(REPLACE(no_hp, ' ', ''), '+62', '0') AS hp_lokal
FROM pelanggan;
Perhatiin urutannya. Spasi dihapus duluan, baru +62 diganti. Kalau kebalik, nomor kayak +62 813 9988 776 nggak bakal kena. Soalnya yang tertulis di data itu +62 diikuti spasi, dan REPLACE nyari kecocokan persis.
Urutan itu penting di REPLACE bersarang. Salah urutan = hasil setengah bersih.
Dataset toko_berkah punya 3.400 baris transaksi. Kolom kode_produk diisi tiga orang berbeda selama dua tahun, dan hasilnya persis kayak yang kamu duga: PRD_001, PRD-001, prd 001.
Waktu aku hitung produk unik pakai COUNT(DISTINCT kode_produk), hasilnya 287. Setelah dinormalisasi, jumlahnya turun jadi 194.
93 kode itu duplikat. Artinya sepertiga katalog produk yang muncul di laporan sebenernya barang yang sama, cuma beda cara nulis.
SELECT UPPER(REPLACE(REPLACE(kode_produk, '_', '-'), ' ', '-')) AS kode_rapi,
COUNT(*) AS jumlah_transaksi,
SUM(total) AS omzet
FROM transaksi
GROUP BY 1
ORDER BY omzet DESC;
REPLACE nyeragamkan pemisahnya, UPPER nyeragamkan huruf besar-kecilnya. Dua fungsi, katalog produk langsung kebaca. Soal UPPER dan LOWER aku bahas terpisah di UPPER dan LOWER SQL.
REPLACE di SELECT itu aman. Data aslinya nggak kesentuh. Tapi begitu kamu pakai di UPDATE, perubahannya permanen.
Urutan yang aku pakai selalu tiga langkah:
SELECT COUNT(*) AS baris_terdampak
FROM pelanggan
WHERE no_hp <> REPLACE(no_hp, '-', '');
Kalau angkanya jauh dari ekspektasi, berhenti. Ada yang salah di logika kamu.SELECT no_hp AS sebelum,
REPLACE(no_hp, '-', '') AS sesudah
FROM pelanggan
WHERE no_hp <> REPLACE(no_hp, '-', '')
LIMIT 20;
Mata kamu bakal nangkep yang query nggak nangkep.BEGIN;
UPDATE pelanggan
SET no_hp = REPLACE(no_hp, '-', '')
WHERE no_hp <> REPLACE(no_hp, '-', '');
-- cek hasilnya dulu
SELECT no_hp FROM pelanggan LIMIT 20;
COMMIT; -- atau ROLLBACK kalau ada yang aneh
WHERE-nya penting. Tanpa itu, database bakal nulis ulang semua baris, termasuk yang udah bersih. Di tabel 3 juta baris, itu beda antara UPDATE 2 detik dan UPDATE 4 menit. Konsep transaksi ini aku bahas lebih dalam di transaksi.
REPLACE(kota, 'jakarta', 'Jakarta') nggak bakal kena JAKARTA. Normalkan dulu: REPLACE(LOWER(kota), 'jakarta', 'Jakarta').REPLACE(NULL, '-', '') hasilnya NULL, bukan string kosong. Bungkus pakai COALESCE kalau perlu.REPLACE nyari teks persis. REGEXP_REPLACE nyari pola. Kalau kamu mau hapus semua karakter yang bukan angka dari nomor HP, satu baris cukup:
-- PostgreSQL
SELECT REGEXP_REPLACE(no_hp, '[^0-9]', '', 'g') AS hp_bersih
FROM pelanggan;
Tanda g di ujung artinya global. Ganti semua yang cocok, bukan cuma yang pertama. Detail sintaksnya bisa kamu cek di dokumentasi fungsi string PostgreSQL.
Aturan praktisnya: karakter yang bisa kamu sebut satu-satu, pakai REPLACE. Pola yang harus dijelasin, pakai REGEXP_REPLACE.
REPLACE ganti satu substring dengan substring lain, panjangnya boleh beda. TRANSLATE (PostgreSQL dan Oracle) ganti karakter satu per satu berdasarkan pemetaan. Buat hapus banyak tanda baca sekaligus, TRANSLATE lebih pendek. Di MySQL dan SQLite, TRANSLATE nggak ada. Tetap pakai REPLACE bersarang.
Ya, di PostgreSQL selalu case-sensitive. REPLACE(kota, 'jakarta', 'Jakarta') nggak bakal kena JAKARTA. Cara aman: normalkan dulu pakai LOWER, baru REPLACE.
Tumpuk REPLACE-nya. Hasil yang di dalam jadi input yang di luar. Kalau tumpukannya udah lewat 5 lapis, mending pakai TRANSLATE atau REGEXP_REPLACE biar query-nya masih kebaca.
Nggak, kalau dipakai di SELECT. Data baru berubah permanen kalau REPLACE dipakai di dalam UPDATE. Biasakan SELECT dulu buat lihat hasilnya, dan bungkus UPDATE besar dalam transaksi biar bisa ROLLBACK.
Hasilnya NULL, bukan string kosong. Hampir semua fungsi string di SQL nularin NULL. Bungkus pakai COALESCE kalau kamu mau nilai default.
Yang perlu nempel di kepala:
Pembersihan data itu 60% pekerjaan analis, dan REPLACE salah satu alat yang paling sering kepakai. Sisanya biasanya soal spasi, yang aku bahas di TRIM SQL.
Latihan query REPLACE langsung di browser tanpa install apa-apa? Coba modul fungsi string di NgulikSQL.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Analisa per kuartal, hari kerja, atau musim jadi ribet kalau tiap query ngitung ulang atribut tanggal. Tabel kalender nyimpen semua atribut itu sekali, biar tinggal di-JOIN.
Laporan penjualan harian sering bolong di hari tanpa transaksi. Ini cara bikin deret tanggal lengkap di SQL biar tiap hari muncul, walau nilainya nol.
Struktur organisasi tersimpan sebagai kolom id_atasan yang saling nunjuk. Ini cara narik rantai jabatan, hitung total bawahan, dan span of control cuma pakai SQL.