Jak utworzyć sparametryzowane zapytanie PDO z instrukcją LIKE?


108

Oto moja próba:

$query = $database->prepare('SELECT * FROM table WHERE column LIKE "?%"');

$query->execute(array('value'));

while ($results = $query->fetch()) 
{
    echo $results['column'];
}

Odpowiedzi:


124

Zrozumiałem to zaraz po tym, jak opublikowałem:

$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->execute(array('value%'));

while ($results = $query->fetch())
{
    echo $results['column'];
}

1
@Andrew: a co, jeśli likeużyto wielu ? w jaki sposób tablica execute powinna być wykonywana w kolejności?
logan

dzięki. miał podobny problem z csharp + Mysql + ODBC, używając w ten sposób żadnych wierszy przy użyciu polecenia „select * from table, gdzie kolumna taka jak '%?%';” ale czy jeśli tak jak ty zrobiłeś "wybierz * z tabeli, gdzie kolumna taka jak?;" i ustaw ciąg parametrów tak: string frag = $ "% {searchFragment}%"; następnie użyj frag jako wartości parametru. Dziwne
sdjuan

2
PDO powinno uciekać przed tym% w wywołaniu execute. Odpowiedź Kaqai jest lepsza
Peter Bagnall

Wydaje się, że warto zauważyć, że najwyższa notatka wniesiona przez użytkowników na stronie dokumentacji PDOStatement :: bindParam oferuje inne podejście: dodaj znak (i) procentu do zmiennej przed jej związaniem.
Dan Robinson,

Spójrz na rozwiązanie Gavina, zaczerpnięte ze strony Your Common Sense, u dołu tego wątku. Prosty. Logiczny.
RationalRabbit

85

Dla tych, którzy używają nazwanych parametrów, oto jak używać LIKEz %częściowym dopasowaniem dla baz danych MySQL :

WHERE nazwa_kolumny LIKE CONCAT („%”,: niebezpieczny ciąg, „%”)

gdzie nazwany parametr jest :dangerousstring.

Innymi słowy, %we własnym zapytaniu używaj jawnie znaków bez zmiany znaczenia, które są oddzielone i na pewno nie są danymi wejściowymi użytkownika.

Edycja: składnia konkatenacji dla baz danych Oracle używa operatora konkatenacji:, ||więc po prostu stanie się:

GDZIE nazwa_kolumny LIKE '%' || : niebezpieczny ciąg || „%”

Istnieją jednak zastrzeżenia, ponieważ @bobince wspomina tutaj, że:

Trudność pojawia się, gdy chcesz zezwolić dosłownym %lub _znak w ciągu wyszukiwania, bez konieczności działać jako zamiennika.

Jest to więc coś, na co należy uważać podczas łączenia polubień i parametryzacji.


6
+1 - wydaje mi się, że to dobre podejście, ponieważ cała konkatenacja odbywa się w bazie danych po zastąpieniu symbolu zastępczego, a to oznacza, że ​​można użyć nazwanych symboli zastępczych. Warto wspomnieć, że powyższa składnia dotyczy Oracle - w MySQL jest to składnia LIKE CONCAT('%', :something, '%'). Źródła: stackoverflow.com/a/661207/201648
Aaron Newton,

1
To nie zadziałało w moim przypadku, ale skierowało mnie na właściwą drogę. Musiałem zrobić LIKE '%': coś '%', żeby to zadziałało.
Christopher Smit,

Wiem, że to nie na temat, ale udało mi się wykonać wstrzyknięcie sql nawet przy użyciu tego stwierdzenia, dlaczego?
Thiago Dias

To nie zadziałało dla mnie, przetestowałem to również za pomocą polecenia SQL, SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )co dałoby mi błąd.
Luzan Baral

@AaronNewton and it means named placeholders can be used. Jak to jest w ogóle problem z nazwanymi symbolami zastępczymi podczas konkatenacji w PHP? Oczywiście konkatenacja w PHP obsługuje zarówno nazwane, jak i pozycyjne i jest bardziej przenośna, ponieważ możesz użyć tego samego zapytania dla dowolnej bazy danych. I naprawdę nie rozumiem, dlaczego tak wielu ludzi, że istnieje jakikolwiek różnica między nazwanych i pozycyjnych zastępcze.
Twój zdrowy rozsądek

18
$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->bindValue(1, "%$value%", PDO::PARAM_STR);
$query->execute();

if (!$query->rowCount() == 0) 
{
    while ($results = $query->fetch()) 
    {
        echo $results['column'] . "<br />\n";
    }       
} 
else 
{
    echo 'Nothing found';
}

1
Czy jest jakaś przewaga używania tego nad zaakceptowaną odpowiedzią? Czy używanie bindValuechroni przed atakami iniekcyjnymi? Zaakceptowana odpowiedź w zasadzie neguje wartość używania ?symboli zastępczych, łącząc ciąg wyszukiwania %z polubieniem w dawnych dniach.
felwithe

Jaki jest sens używania negacji przed $ query-> rowCount () == 0? Czy to rzeczywiście ma sens?
ssi-anik

15

Możesz także spróbować tego. Mam podobny problem, ale po badaniach uzyskałem wynik.

$query = $pdo_connection->prepare('SELECT * FROM table WHERE column LIKE :search');

$stmt= $pdo_connection->prepare($query);

$stmt->execute(array(':search' => '%'.$search_term.'%'));

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

print_r($result);

Edytowałem Twój post, aby umieścić kod w bloku kodu - możesz przeczytać więcej o formatowaniu postów na stackoverflow.com/help/formatting . Jakiś inny użytkownik zdecydował się zagłosować przeciw Twojej odpowiedzi bez pozostawiania komentarza, więc nie jestem pewien, co jest przyczyną takiego głosu.
josliber

2
Powtarzam, nie głosowałem nad twoim pytaniem; ktoś inny przegłosował.
josliber

3

To działa:

search `table` where `column` like concat('%', :column, '%')

2

Mam to z urojeń php

$search = "%$search%";
$stmt  = $pdo->prepare("SELECT * FROM table WHERE name LIKE ?");
$stmt->execute([$search]);
$data = $stmt->fetchAll();

U mnie to działa, bardzo proste. Jak mówi, przed wysłaniem go do zapytania należy najpierw „przygotować nasz kompletny dosłowny”


0

PDO ucieka „%” (może prowadzić do wstrzyknięcia sql) : Użycie poprzedniego kodu da pożądane rezultaty, gdy szuka się dopasowania częściowych ciągów, ALE jeśli odwiedzający wpisze znak „%”, nadal otrzymasz wyniki, nawet jeśli tego nie zrobisz nie mam nic zapisanego w bazie danych (może to prowadzić do wstrzyknięć sql)

Wypróbowałem wiele wariacji, wszystkie z tym samym rezultatem PDO ucieka przed „%” wiodącymi niechcianymi / niespodziewanymi wynikami wyszukiwania.

Pomyślałam, że warto się tym podzielić, jeśli ktoś znalazł przy nim jakieś słowo, proszę o podzielenie się nim


1
To pochodzi z podręcznika: us3.php.net/manual/en/pdo.prepared-statements.php To kolejny post na ten temat: stackoverflow.com/questions/22030451/ ... Naprawdę chciałbym poznać Twoją opinię na temat ten problem.
Ozkar R

1
Możliwe rozwiązanie (Nie testowano) Użyj CONCAT , na przykład: $ sql = „SELECT item_title FROM item WHERE item_title LIKE CONCAT ('%',?, '%')”; Źródła
Ozkar R

3
PDO nie wymyka się%. To twój kod robi to źle. Aby uzyskać rozwiązanie, powinieneś przeczytać odpowiedzi już podane tutaj
Your Common Sense

Dziękuję za sugestie. W każdym razie testowany kod był kodem z podręcznika, używając symbolu zastępczego, aby uniknąć iniekcji SQL, nadal otrzymuję ten sam wynik. Przykład # 6 Nieprawidłowe użycie zastępczego PDO powoduje zmianę% przy użyciu powyższego kodu, a nie mojego kodu. Jestem nowy na forum i być może nie rozumiem, jak działa tutaj proces komentowania, publikowania postów i reputacji. Będę o tym pamiętać przy następnym, ponieważ na podstawie poprzedniego komentarza potrzebujesz reputacji, aby pomagać innym lub komentować. dzięki.
Ozkar R
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.