Perbandingan = menuntut teks yang persis sama — ia tidak bisa menjawab “produk mana yang namanya diawali kata Peng?” atau “promo mana yang mengandung angka 50%?”. Untuk pertanyaan berpola, SQL menyediakan operator LIKE dengan dua wildcard: % untuk segala jumlah karakter dan _ untuk tepat satu karakter. Varian ILIKE melakukan hal yang sama tanpa memedulikan besar kecil huruf. Pada chapter ini kita membedah kedua wildcard itu, menguji sensitivitas huruf, lalu mempelajari karakter escape — satu-satunya cara mencari teks yang benar-benar mengandung tanda % itu sendiri, seperti label promo Diskon 50% di tabel latihan kita.
Menyiapkan Tabel Latihan #
Tabel produk Toko Maju Jaya yang sama dipakai untuk terakhir kalinya di rangkaian chapter filtering dasar ini. Kolom nama menyediakan variasi huruf besar-kecil yang dibutuhkan demo ILIKE, dan kolom promo dengan nilai seperti Diskon 50% menjadi bahan utama demo escape:
CREATE TABLE produk (
id integer PRIMARY KEY,
nama text NOT NULL,
kategori text NOT NULL,
harga numeric(10, 2) NOT NULL,
stok integer NOT NULL,
aktif boolean NOT NULL,
tanggal_masuk date,
promo text
);
INSERT INTO produk (id, nama, kategori, harga, stok, aktif, tanggal_masuk, promo) VALUES
(1, 'Buku Tulis 58', 'alat tulis', 4500, 120, true, DATE '2025-11-10', NULL),
(2, 'Pulpen Hitam', 'alat tulis', 3000, 200, true, DATE '2025-12-01', 'Diskon 10%'),
(3, 'Kertas HVS A4', 'kertas', 55000, 40, true, DATE '2026-01-05', 'Diskon 50%'),
(4, 'Stapler Besar', 'alat tulis', 24000, 15, false, DATE '2026-01-20', NULL),
(5, 'Amplop Coklat', 'kertas', 1500, 500, true, DATE '2026-02-14', NULL),
(6, 'Penghapus', 'alat tulis', 2000, 0, false, DATE '2026-02-14', NULL),
(7, 'Kalkulator Solar', 'elektronik', 185000, 8, true, DATE '2026-03-02', 'Diskon 25%'),
(8, 'Penggaris 30cm', 'alat tulis', 3500, 85, true, DATE '2026-03-15', 'Diskon 5%');Output yang Dihasilkan:
CREATE TABLE
INSERT 0 8Dua Wildcard: % dan _ #
Pola LIKE dibangun dari teks biasa plus dua karakter istimewa. Tabel berikut merangkum keduanya:
| Wildcard | Arti | Contoh pola | Cocok dengan |
|---|---|---|---|
% | nol atau lebih karakter apa pun | 'Peng%' | Penghapus, Penggaris 30cm |
% di tengah | segala teks di antaranya | '%30cm%' | Penggaris 30cm |
_ | tepat satu karakter apa pun | '_enghapus%' | Penghapus |
_ di tengah | tepat satu karakter di posisinya | 'Penggaris 30_m' | Penggaris 30cm |
Satu aturan penting sebelum melihat contoh: pola LIKE harus cocok dengan seluruh nilai kolom, bukan sebagian — perilakunya seperti pola yang dijangkar di dua ujung. Mencari nama yang “mengandung” kata tertentu karena itu selalu ditulis dengan % di kedua sisi:
SELECT id, nama FROM produk
WHERE nama LIKE 'Peng%'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama LIKE '%Hitam'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama LIKE '%30cm%'
ORDER BY id;Output yang Dihasilkan:
id | nama
----+----------------
6 | Penghapus
8 | Penggaris 30cm
(2 rows)
id | nama
----+--------------
2 | Pulpen Hitam
(1 row)
id | nama
----+----------------
8 | Penggaris 30cm
(1 row)Mari kita bedah tiga pola itu:
nama LIKE 'Peng%'menjaring dua produk yang namanya dimulai denganPeng:PenghapusdanPenggaris 30cm. Wildcard%di ujung menyerap sisa nama sepanjang apa pun.nama LIKE '%Hitam'menjaring satu produk yang namanya berakhir denganHitam. Tanpa%di awal, pola ini menuntut nama dimulai persis denganHitam—Pulpen Hitamhanya lolos karena%-nya menjelma menjadiPulpen.nama LIKE '%30cm%'menjaring nama yang mengandung30cmdi mana pun posisinya — pola “mengandung” klasik dengan%mengapit di dua sisi.
Wildcard _ Mewakili Tepat Satu Karakter #
Wildcard _ lebih ketat dari %: satu garis bawah mewakili tepat satu karakter — bukan nol, bukan dua. Perbandingan berikut memperlihatkan bedanya pada data yang sama:
SELECT id, nama FROM produk
WHERE nama LIKE '_enghapus%'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama LIKE 'Penggaris 30_m'
ORDER BY id;Output yang Dihasilkan:
id | nama
----+-----------
6 | Penghapus
(1 row)
id | nama
----+----------------
8 | Penggaris 30cm
(1 row)Pola '_enghapus%' menjaring Penghapus — karakter P diambil alih oleh _, sisanya harus cocok huruf demi huruf. Bandingkan dengan 'Peng%' di bagian sebelumnya yang menjaring dua produk: _ menolak Penggaris 30cm karena huruf kedua Penggaris adalah e, bukan n. Pola kedua, 'Penggaris 30_m', memperlihatkan _ di tengah pola: satu karakter apa pun boleh duduk di posisi itu — pada Penggaris 30cm, posisi itu diisi huruf c. Karena _ selalu tepat satu karakter, pola seperti '_ng%' akan menolak nama yang hanya satu huruf pendeknya tidak pas — ketelitian inilah yang membuat _ berguna untuk pola dengan panjang tetap, misalnya kode voucher 'DISC_2026_%'.
LIKE versus ILIKE: Sensitivitas Huruf #
LIKE membandingkan huruf besar-kecil secara sensitif — di server dengan locale C, 'hvs' dan 'HVS' adalah byte yang berbeda. ILIKE adalah varian case-insensitive dari LIKE yang dimiliki PostgreSQL (bukan standar SQL):
SELECT id, nama FROM produk
WHERE nama LIKE '%hvs%'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama ILIKE '%hvs%'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama ILIKE 'p%'
ORDER BY id;Output yang Dihasilkan:
id | nama
----+------
(0 rows)
id | nama
----+---------------
3 | Kertas HVS A4
(1 row)
id | nama
----+----------------
2 | Pulpen Hitam
6 | Penghapus
8 | Penggaris 30cm
(3 rows)Tiga hasil itu menceritakan perbedaannya dengan lengkap:
LIKE '%hvs%'mengembalikan nol baris — namaKertas HVS A4menyimpanHVSdengan huruf besar, danLIKEmenolak menyamakannya denganhvs.ILIKE '%hvs%'menjaringKertas HVS A4— huruf besar-kecil diabaikan sepenuhnya, pola dan data dicocokkan tanpa memedulikan casing.ILIKE 'p%'menjaring semua nama berawalan huruf p dalam casing apa pun:Pulpen Hitam,Penghapus, danPenggaris 30cm.
Untuk data yang namanya dicampur-campur casingnya (hasil impor, input pengguna tanpa normalisasi), ILIKE sering menjadi penyelamat pencarian. Alternatifnya adalah menormalkan kedua sisi dengan lower(nama) LIKE 'peng%' — pola yang portabel ke database lain yang tidak punya ILIKE, dengan catatan fungsi lower() pada kolom membuat index biasa tidak terpakai kecuali dibuat index ekspresi.
Karakter Escape untuk % Literal #
Bagaimana mencari promo yang mengandung tanda persen itu sendiri? Pola '%50%%' tidak menjawabnya — dua % bersebelahan tetap dibaca sebagai wildcard. Solusinya adalah karakter escape: satu karakter yang dinaikkan derajatnya untuk membatalkan makna istimewa karakter sesudahnya. Secara default PostgreSQL memakai garis miring terbalik (\) sebagai escape, dan klausa ESCAPE membuatnya eksplisit:
SELECT id, nama, promo FROM produk
WHERE promo LIKE '%50\%%' ESCAPE '\'
ORDER BY id;
SELECT id, nama, promo FROM produk
WHERE promo LIKE '%25\%%'
ORDER BY id;
SELECT 'Diskon 50%' LIKE '%\%%' AS mengandung_persen,
'Buku Tulis 58' LIKE '%\%%' AS tanpa_persen;Output yang Dihasilkan:
id | nama | promo
----+---------------+------------
3 | Kertas HVS A4 | Diskon 50%
(1 row)
id | nama | promo
----+------------------+------------
7 | Kalkulator Solar | Diskon 25%
(1 row)
mengandung_persen | tanpa_persen
-------------------+--------------
t | f
(1 row)Pola '%50\%%' terlihat seperti sandi, tetapi dibaca dari kiri ke kanan menjadi masuk akal:
%— nol atau lebih karakter apa pun (penyerap awal).50— teks biasa yang harus ada.\%— tanda persen literal, karena\membatalkan peran%sebagai wildcard.%— wildcard penutup, menyerap sisa teks apa pun setelah persen.
Hasilnya: satu baris — Kertas HVS A4 dengan promo Diskon 50%. Query kedua memakai pola yang sama tanpa klausa ESCAPE dan tetap bekerja, karena \ memang escape default LIKE di PostgreSQL; klausa ESCAPE '\' hanya membuatnya eksplisit. Query ketiga menguji pola minimal '%\%%' (mengandung satu persen literal): cocok untuk 'Diskon 50%' dan menolak 'Buku Tulis 58' yang tidak punya tanda persen. Mencari teks yang mengandung backslash literal mengikuti logika yang sama — pola backslash di-escape dengan backslash lain, misalnya '%\\%'.
Sekilas Operator Regex #
LIKE dengan dua wildcardnya kuat untuk pola sederhana, tetapi pola seperti “nama yang mengandung angka” tetap canggung — karakter angka harus disebut satu-satu. PostgreSQL punya senjata yang jauh lebih ekspresif: operator ~ untuk regular expression. Dua contoh singkat berikut hanya sepintas — pembahasan penuhnya menempati chapter Regular Expressions di section ini:
SELECT id, nama FROM produk
WHERE nama ~ '^Peng'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama ~ '[0-9]+'
ORDER BY id;Output yang Dihasilkan:
id | nama
----+----------------
6 | Penghapus
8 | Penggaris 30cm
(2 rows)
id | nama
----+----------------
1 | Buku Tulis 58
3 | Kertas HVS A4
8 | Penggaris 30cm
(3 rows)Pola '^Peng' berarti “diawali Peng” — hasilnya sama dengan LIKE 'Peng%', dan tabel perbandingannya pun lengkap: ^ dan $ di regex berperan seperti jangkar, menggantikan posisi % di LIKE. Pola '[0-9]+' — “mengandung satu atau lebih digit” — menjaring tiga nama: Buku Tulis 58, Kertas HVS A4, dan Penggaris 30cm. Pola semacam ini mustahil ditulis dengan LIKE tanpa merangkai puluhan variasi wildcard. Ketika kebutuhan pola melampaui % dan _, regex adalah jawabannya.
Dari WHERE sederhana sampai pencocokan pola, perangkat filtering teks kita kini lengkap: perbandingan persis, rentang, daftar, dan pola dengan escape. Satu topik penyaringan masih tersisa dan menjadi semakin penting justru karena semua operator di section ini “gagal diam-diam” terhadapnya: NULL. Operator IS NULL, IS NOT NULL, dan IS DISTINCT FROM — topik chapter berikutnya — adalah alat yang menutup celah itu.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
buat-tabel.sql
Unduh berkasCREATE TABLE produk (
id integer PRIMARY KEY,
nama text NOT NULL,
kategori text NOT NULL,
harga numeric(10, 2) NOT NULL,
stok integer NOT NULL,
aktif boolean NOT NULL,
tanggal_masuk date,
promo text
);
INSERT INTO produk (id, nama, kategori, harga, stok, aktif, tanggal_masuk, promo) VALUES
(1, 'Buku Tulis 58', 'alat tulis', 4500, 120, true, DATE '2025-11-10', NULL),
(2, 'Pulpen Hitam', 'alat tulis', 3000, 200, true, DATE '2025-12-01', 'Diskon 10%'),
(3, 'Kertas HVS A4', 'kertas', 55000, 40, true, DATE '2026-01-05', 'Diskon 50%'),
(4, 'Stapler Besar', 'alat tulis', 24000, 15, false, DATE '2026-01-20', NULL),
(5, 'Amplop Coklat', 'kertas', 1500, 500, true, DATE '2026-02-14', NULL),
(6, 'Penghapus', 'alat tulis', 2000, 0, false, DATE '2026-02-14', NULL),
(7, 'Kalkulator Solar', 'elektronik', 185000, 8, true, DATE '2026-03-02', 'Diskon 25%'),
(8, 'Penggaris 30cm', 'alat tulis', 3500, 85, true, DATE '2026-03-15', 'Diskon 5%');
escape.sql
Unduh berkasSELECT id, nama, promo FROM produk
WHERE promo LIKE '%50\%%' ESCAPE '\'
ORDER BY id;
SELECT id, nama, promo FROM produk
WHERE promo LIKE '%25\%%'
ORDER BY id;
SELECT 'Diskon 50%' LIKE '%\%%' AS mengandung_persen,
'Buku Tulis 58' LIKE '%\%%' AS tanpa_persen;
ilike.sql
Unduh berkasSELECT id, nama FROM produk
WHERE nama LIKE '%hvs%'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama ILIKE '%hvs%'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama ILIKE 'p%'
ORDER BY id;
like-dasar.sql
Unduh berkasSELECT id, nama FROM produk
WHERE nama LIKE 'Peng%'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama LIKE '%Hitam'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama LIKE '%30cm%'
ORDER BY id;
regex-preview.sql
Unduh berkasSELECT id, nama FROM produk
WHERE nama ~ '^Peng'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama ~ '[0-9]+'
ORDER BY id;
underscore.sql
Unduh berkasSELECT id, nama FROM produk
WHERE nama LIKE '_enghapus%'
ORDER BY id;
SELECT id, nama FROM produk
WHERE nama LIKE 'Penggaris 30_m'
ORDER BY id;