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'];
}
Andrew G. Johnson
źródło

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'];
}
Andrew G. Johnson
źródło
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.

Kzqai
źródło
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';
}
marynarka
źródło
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);
Vijaysinh Parmar
źródło
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, '%')
kjdion84
źródło
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”

gavin
źródło
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

Ozkar R
źródło
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