Wie erstelle ich eine PDO-parametrisierte Abfrage mit einer LIKE-Anweisung?

107

Hier ist mein Versuch:

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

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

while ($results = $query->fetch()) 
{
    echo $results['column'];
}
Andrew G. Johnson
quelle

Antworten:

124

Ich habe es gleich nach dem Posten herausgefunden:

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

while ($results = $query->fetch())
{
    echo $results['column'];
}
Andrew G. Johnson
quelle
1
@ Andrew: Was ist, wenn mehrere likeverwendet werden? Wie soll das Execute-Array der Reihe nach ausgeführt werden?
Logan
Vielen Dank. hatte ein ähnliches Problem mit csharp + Mysql + ODBC, als würde es keine Zeilen zurückgeben, wenn "select * from table where column like '%?%';" Aber wenn ich es mag, haben Sie "* aus der Tabelle ausgewählt, in der die Spalte gefällt?" und setzen Sie den Parameter string so: string frag = $ "% {searchFragment}%"; Verwenden Sie dann frag als Parameterwert. Weird
sdjuan
2
PDO sollte diesen% im Ausführungsaufruf entkommen. Kaqais Antwort ist besser
Peter Bagnall
Es ist erwähnenswert, dass der vom Benutzer am häufigsten bereitgestellte Hinweis auf der PDOStatement :: bindParam-Dokumentationsseite einen anderen Ansatz bietet: Fügen Sie der Variablen die Prozentzeichen hinzu, bevor Sie sie binden.
Dan Robinson
Werfen Sie einen Blick auf die Lösung von gavin, die Sie auf der Seite von Your Common Sense am Ende dieses Threads finden. Einfach. Logisch.
RationalRabbit
85

Für diejenigen , benannte Parameter verwenden, ist hier, wie die Verwendung LIKEmit %Teilübereinstimmung für MySQL - Datenbanken :

WHERE Spaltenname LIKE CONCAT ('%' ,: gefährliche Zeichenfolge, '%')

wo der genannte Parameter ist :dangerousstring.

Mit anderen Worten, verwenden Sie %in Ihrer eigenen Abfrage explizit nicht entkoppelte Zeichen, die getrennt sind und definitiv nicht die Benutzereingabe sind.

Bearbeiten: Die Verkettungssyntax für Oracle-Datenbanken verwendet den Verkettungsoperator : ||, wird also einfach:

WHERE Spaltenname LIKE '%' || : gefährliche Saite || '%'

Es gibt jedoch Vorbehalte, da @bobince hier erwähnt , dass:

Die Schwierigkeit tritt auf, wenn Sie ein Literal %oder _Zeichen in der Suchzeichenfolge zulassen möchten , ohne dass es als Platzhalter fungiert.

Das ist also etwas anderes, auf das Sie achten müssen, wenn Sie Like und Parametrisierung kombinieren.

Kzqai
quelle
6
+1 - Dies scheint mir ein guter Ansatz zu sein, da die gesamte Verkettung in der Datenbank erfolgt, nachdem der Platzhalter ersetzt wurde, und dies bedeutet, dass benannte Platzhalter verwendet werden können. Es ist erwähnenswert, dass die obige Syntax für Oracle ist - in MySQL ist die Syntax LIKE CONCAT('%', :something, '%'). Referenz: stackoverflow.com/a/661207/201648
Aaron Newton
1
Das hat bei mir nicht genau funktioniert, aber mich auf den richtigen Weg gebracht. Ich musste LIKE '%' machen: etwas '%', damit es funktioniert.
Christopher Smit
Ich weiß, dass dies kein Thema ist, aber ich konnte die SQL-Injektion sogar mit dieser Anweisung durchführen. Warum?
Thiago Dias
Dies hat bei mir nicht funktioniert, ich habe es auch mit dem SQL-Befehl getestet, SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )dies würde mir einen Fehler geben.
Luzan Baral
@ AaronNewton and it means named placeholders can be used. Wie ist es überhaupt ein Problem mit benannten Platzhaltern, wenn Sie in PHP verketten? Offensichtlich unterstützt die Verkettung in PHP sowohl Named als auch Positional und ist portabler, da Sie für jede Datenbank dieselbe Abfrage verwenden können. Ich verstehe nicht wirklich, warum so viele Leute denken, dass es einen Unterschied zwischen benannten und positionellen Platzhaltern gibt.
Ihr
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';
}
Blazer
quelle
1
Gibt es einen Vorteil gegenüber der akzeptierten Antwort? Schützt die Verwendung bindValuevor Injektionsangriffen? Die akzeptierte Antwort negiert im Grunde den Wert der Verwendung von ?Platzhaltern, indem die Suchzeichenfolge so verkettet wird, %dass sie in den alten Tagen gefällt.
Felwithe
Was bringt es, die Negation vor $ query-> rowCount () == 0 zu verwenden? Ist das eigentlich sinnvoll?
ssi-anik
14

Sie können diesen auch ausprobieren. Ich stehe vor einem ähnlichen Problem, habe aber nach Recherchen ein Ergebnis erzielt.

$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
quelle
Ich habe Ihren Beitrag bearbeitet, um den Code in einen Codeblock einzufügen . Weitere Informationen zur Formatierung von Beiträgen finden Sie unter stackoverflow.com/help/formatting . Ein anderer Benutzer hat sich dafür entschieden, Ihre Antwort ohne Kommentar abzugeben, daher bin ich mir über die Ursache der Ablehnung nicht sicher.
Josliber
2
Um es zu wiederholen, ich habe nicht über Ihre Frage abgestimmt. jemand anderes hat herabgestimmt.
Josliber
3

Das funktioniert:

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

Ich habe das von PHP-Wahnvorstellungen bekommen

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

Und es funktioniert bei mir sehr einfach. Wie er sagt, müssen Sie "zuerst unser vollständiges Literal vorbereiten", bevor Sie es an die Abfrage senden

Gavin
quelle
0

PDO entgeht "%" (kann zu SQL-Injection führen) : Die Verwendung des vorherigen Codes führt zu den gewünschten Ergebnissen, wenn Teilzeichenfolgen abgeglichen werden sollen. ABER wenn ein Besucher das Zeichen "%" eingibt, erhalten Sie auch dann Ergebnisse, wenn Sie dies nicht tun. Sie haben nichts in der Datenbank gespeichert (dies kann zu SQL-Injektionen führen).

Ich habe viele Variationen ausprobiert, alle mit dem gleichen Ergebnis. PDO entgeht "%" und führt zu unerwünschten / nicht aufgeregten Suchergebnissen.

Ich dachte, es lohnt sich zu teilen, wenn jemand ein Wort darüber gefunden hat, teilen Sie es bitte

Ozkar R.
quelle
1
Dies ist aus dem Handbuch: us3.php.net/manual/en/pdo.prepared-statements.php Dies ist ein weiterer Beitrag zum Thema: stackoverflow.com/questions/22030451/… Ich würde gerne Ihre Meinung dazu wissen diese issu.
Ozkar R
1
Mögliche Lösung (nicht getestet) Verwenden Sie CONCAT wie: $ sql = "SELECT item_title FROM item WHERE item_title LIKE CONCAT ('%',?, '%')"; Referenz: blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard
Ozkar R
3
PDO entgeht% nicht. Es ist Ihr Code, der es falsch macht. Für die Lösung sollten Sie die Antworten lesen, die bereits hier bereitgestellt wurden
Ihr gesunder Menschenverstand
Vielen Dank für Ihre Vorschläge. Wie auch immer, der getestete Code war der Code aus dem Handbuch, der Platzhalter verwendet, um SQL-Injection zu vermeiden. Ich erhalte immer noch das gleiche Ergebnis. Beispiel 6 Die ungültige Verwendung von Platzhalter- PDO entgeht% mit dem obigen Code, nicht meinem Code. Ich bin neu im Forum und verstehe möglicherweise nicht, wie der Prozess von Kommentaren, Posts und Reputationen hier funktioniert. Ich werde dies bei meinem nächsten berücksichtigen, da Sie basierend auf dem vorherigen Kommentar Reputationen benötigen, um anderen zu helfen oder Kommentare abzugeben. Vielen Dank.
Ozkar R