String kueri MySQL berisi

307

Saya sudah mencoba mencari tahu bagaimana saya bisa membuat kueri dengan MySQL yang memeriksa apakah nilai (string $haystack) di kolom tertentu berisi data (string $needle) tertentu, seperti ini:

mysql_query("
SELECT *
FROM `table`
WHERE `column`.contains('{$needle}')
");

Di PHP, fungsinya dipanggil substr($haystack, $needle), jadi mungkin:

WHERE substr(`column`, '{$needle}')=1
arik
sumber

Jawaban:

437

Sebenarnya cukup sederhana:

mysql_query("
SELECT *
FROM `table`
WHERE `column` LIKE '%{$needle}%'
");

Ini %adalah wildcard untuk set karakter apa pun (tidak ada, satu atau banyak). Perhatikan bahwa ini bisa lambat pada kumpulan data yang sangat besar sehingga jika basis data Anda tumbuh Anda harus menggunakan indeks teks lengkap.

Wolph
sumber
1
Ini hanya akan berfungsi jika Anda menggunakan kueri yang disiapkan. Jika Anda menggunakan string aktual di sana (mis. Skrip peningkatan sql liquibase) maka pertimbangkan INSTR yang disebutkan di bawah ini). Ini karena jika string Anda berisi% maka Anda akan mulai mencocokkan sesuatu dengannya.
Ryan Shillington
2
saya tahu tentang pertanyaan seperti, namun hari ini saya ingin mencari tahu apakah ada nilai tertentu dalam string di beberapa kolom saya googling untuk itu .. Mengapa saya tidak pernah memikirkannya sebelumnya ??
Sizzling Code
1
apakah case ini sensitif?
Kiwi
2
@angry_kiwi: dengan column LIKE '...'itu peka huruf besar kecil, dengan column LIKE BINARY '...'itu peka huruf besar kecil
Wolph
2
Saya terkejut bahwa LIKEdiusulkan untuk memeriksa substring karena operator ini menggunakan dua karakter wildcard: %dan _. Ini berarti jika string $ jarum Anda mengandung salah satu karakter khusus ini maka hasilnya tidak seperti yang diharapkan sama sekali. (-1) untuk balasan ini, dan (+1) untuk balasan INSTR.
Skrol29
144

Menggunakan:

SELECT *
  FROM `table`
 WHERE INSTR(`column`, '{$needle}') > 0

Referensi:

OMG Ponies
sumber
pasti LIKE lebih cepat daripada INSTR?
chris
17
@ Oedo: Tergantung. LIKE %...%tidak akan menggunakan indeks jika ada, jadi mereka harus setara; LIKE ...%akan menggunakan indeks jika ada. Jika kinerja adalah masalah nyata, Pencarian Teks Lengkap (FTS) akan menjadi pendekatan yang lebih baik.
OMG Ponies
sempurna. apa yang saya cari.
arik
2
Saya suka solusi ini karena sebenarnya tidak ada cara untuk mengurutkan hal-hal sesuai dengan kehadiran substring dengan likeoperator. Dengan instrfrasa dapat dipesan seperti iniselect * from table order by instr(col1,"mystring")
Radacina
Saya ingin mencari _ di bidang dan itu berhasil. Terima kasih
Safeer Ahmed
53
WHERE `column` LIKE '%$needle%'
chris
sumber
2
saat mencari karakter _ (garis bawah) kueri SEPERTI '% _%' tidak berfungsi, untuk beberapa alasan ia mengembalikan semua string bahkan tanpa _
Wojtek
1
@Wojtek _ adalah wildcard untuk setiap karakter tunggal, jadi jika Anda ingin mencari garis bawah literal, Anda harus menghindarinya. Lihat permintaan MySQL LIKE dengan garis bawah .
jkmartindale
29

Tambang menggunakan LOCATEdi mysql:

LOCATE (substr, str), LOCATE (substr, str, pos)

Fungsi ini multi-byte aman, dan case-sensitive hanya jika setidaknya satu argumen adalah string biner.

Dalam kasus Anda:

mysql_query("
SELECT * FROM `table`
WHERE LOCATE('{$needle}','column') > 0
");
risnandar
sumber
11
'kolom' harus berupa kolom (tanpa tanda kutip)
Wojtek
10

Selain jawaban dari @WoLpH.

Saat menggunakan LIKEkata kunci, Anda juga memiliki kemampuan untuk membatasi arah string yang cocok. Sebagai contoh:

Jika Anda mencari string yang dimulai dengan $needle:

... WHERE column LIKE '{$needle}%'

Jika Anda mencari string yang diakhiri dengan $needle:

... WHERE column LIKE '%{$needle}'
Joshua Powell
sumber
3

Ketahuilah bahwa ini berbahaya:

WHERE `column` LIKE '%{$needle}%'

lakukan dulu:

$needle = mysql_real_escape_string($needle);

jadi itu akan mencegah kemungkinan serangan.

Alejandro Moreno
sumber
7
* Beberapa kemungkinan serangan. Juga, mysql_real_escape_stringakan ditinggalkan dalam rilis PHP masa depan.
Jack Tuck
11
Anda harus menggunakan pernyataan yang sudah disiapkan , dan meninggalkan escaping ke PHP. $stmt = $dbh->prepare("Where 'column' LIKE '{:needle}'"); $stmt->bindParam(':needle', $needle); $stmt->execute();
cloudworks
3

Anda mungkin mencari find_in_setfungsi:

Where find_in_set($needle,'column') > 0

Fungsi ini berfungsi seperti in_arrayfungsi dalam PHP

Andres
sumber