Ciąg zapytania MySQL zawiera


307

Próbowałem dowiedzieć się, w jaki sposób mogę wykonać zapytanie za pomocą MySQL, które sprawdza, czy wartość (ciąg $haystack) w określonej kolumnie zawiera określone dane (ciąg $needle), takie jak:

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

W PHP funkcja jest wywoływana substr($haystack, $needle), więc może:

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

Odpowiedzi:


437

Właściwie dość proste:

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

%Jest wieloznaczny dla wszelkich znaków Set (brak, jednego lub wielu). Zauważ, że może się to spowolnić w przypadku bardzo dużych zestawów danych, więc jeśli baza danych rośnie, musisz użyć indeksów pełnotekstowych.


1
Działa to tylko wtedy, gdy używasz przygotowanego zapytania. Jeśli używasz tam prawdziwego ciągu (np. Skryptu aktualizacyjnego upłynnienia SQL), rozważ INSTR wymienione poniżej). Wynika to z faktu, że jeśli Twój ciąg zawiera%, zaczniesz z nim pasować.
Ryan Shillington

2
wiem o podobnych zapytaniach, a jednak dzisiaj chciałem dowiedzieć się, czy istnieje pewna wartość w łańcuchu w jakiejś kolumnie, w której szukałem go. Dlaczego nigdy wcześniej o tym nie myślałem?
Sizzling Code

1
czy w tym rozróżniana jest wielkość liter?
zły kiwi

2
@angry_kiwi: z column LIKE '...'tym nie rozróżnia wielkości liter, z column LIKE BINARY '...'tym jest rozróżniana
wielkość

2
Dziwi mnie, że LIKEzaproponowano sprawdzenie podciągu, ponieważ ten operator używa dwóch znaków wieloznacznych: %i _. Oznacza to, że jeśli igła $ ciągu zawiera jeden z tych znaków specjalnych, wówczas wyniki nie są zgodne z oczekiwaniami. (-1) dla tej odpowiedzi i (+1) dla odpowiedzi INSTR.
Skrol29

144

Posługiwać się:

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

Odniesienie:


na pewno LIKE jest szybszy niż INSTR?
Chris

17
@oedo: Zależy. LIKE %...%nie użyje indeksu, jeśli jest obecny, więc powinny być równoważne; LIKE ...%użyłby indeksu, jeśli jest obecny. Jeśli wydajność stanowi poważny problem, lepszym rozwiązaniem byłoby wyszukiwanie pełnotekstowe (FTS).
Kucyki OMG

doskonały. właśnie tego szukałem.
arik

2
Podoba mi się to rozwiązanie, ponieważ w rzeczywistości nie ma sposobu, aby posortować rzeczy według obecności podciągu z likeoperatorem. Z instrfrazą można zamówić w ten sposóbselect * from table order by instr(col1,"mystring")
Radacina

Chciałem wyszukać _ w polu i zadziałało. Dzięki
Safeer Ahmed,

53
WHERE `column` LIKE '%$needle%'

2
podczas wyszukiwania znaku _ (podkreślenie) zapytanie JAK '% _%' nie działa, z jakiegoś powodu zwraca wszystkie ciągi nawet bez _
Wojtek

1
@Wojtek _ jest znakiem wieloznacznym dla każdego pojedynczego znaku, więc jeśli chcesz wyszukać dosłowny znak podkreślenia, musisz go uciec. Zobacz zapytanie LIKE MySQL z podkreśleniem .
jkmartindale

29

Mój używa LOCATEw mysql:

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

Ta funkcja jest bezpieczna dla wielu bajtów i rozróżnia małe i wielkie litery tylko wtedy, gdy co najmniej jeden argument jest łańcuchem binarnym.

W Twoim przypadku:

mysql_query("
SELECT * FROM `table`
WHERE LOCATE('{$needle}','column') > 0
");

11
„kolumna” powinna być kolumną (bez cudzysłowów)
Wojtek

10

Oprócz odpowiedzi z @WoLpH.

Korzystając ze LIKEsłowa kluczowego, możesz również ograniczyć kierunek, w którym pasuje ciąg. Na przykład:

Jeśli szukasz ciągu rozpoczynającego się od $needle:

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

Jeśli szukałeś ciągu, który kończy się na $needle:

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

3

pamiętaj, że jest to niebezpieczne:

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

Ty pierwszy:

$needle = mysql_real_escape_string($needle);

zapobiegnie to możliwym atakom.


7
* Niektóre możliwe ataki. Ponadto, mysql_real_escape_stringbędzie przestarzałe w przyszłych wersjach PHP.
Jack Tuck

11
Powinieneś użyć przygotowanych instrukcji i pozostawić ucieczkę do PHP. $stmt = $dbh->prepare("Where 'column' LIKE '{:needle}'"); $stmt->bindParam(':needle', $needle); $stmt->execute();
Cloudworks

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.