Come si crea una query parametrizzata PDO con un'istruzione LIKE?


107

Ecco il mio tentativo:

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

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

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

Risposte:


124

L'ho capito subito dopo aver pubblicato:

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

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

1
@Andrew: cosa succede se likesi usa più? come deve essere eseguito l'array di esecuzione in ordine?
logan

Grazie. ha avuto un problema simile con csharp + Mysql + ODBC utilizzando come se non restituisse alcuna riga utilizzando "seleziona * dalla tabella dove colonna come '%?%';" ma se lo faccio come hai fatto "seleziona * dalla tabella in cui colonna piace?;" e imposta la stringa del parametro così: string frag = $ "% {searchFragment}%"; quindi utilizzare frag per il valore del parametro. Strano
sdjuan

2
PDO dovrebbe sfuggire a quel% nella chiamata di esecuzione. La risposta di Kaqai è migliore
Peter Bagnall

Sembra che valga la pena notare che la nota principale fornita dagli utenti nella pagina della documentazione di PDOStatement :: bindParam offre un approccio diverso: aggiungi i segni di percentuale alla variabile prima di collegarla.
Dan Robinson

Dai un'occhiata alla soluzione di gavin, presa dalla pagina di Your Common Sense, in fondo a questo thread. Semplice. Logico.
RationalRabbit

85

Per coloro che utilizzano parametri denominati, ecco come utilizzarli LIKEcon la %corrispondenza parziale per i database MySQL :

WHERE nome_colonna LIKE CONCAT ('%',: dangerousstring, '%')

dove si trova il parametro denominato :dangerousstring.

In altre parole, usa %segni esplicitamente senza caratteri di escape nella tua query che sono separati e sicuramente non l'input dell'utente.

Modifica: la sintassi di concatenazione per i database Oracle utilizza l'operatore di concatenazione:, ||quindi diventerà semplicemente:

WHERE nome_colonna LIKE '%' || : dangerousstring || '%'

Tuttavia ci sono avvertimenti in quanto @bobince menziona qui che:

La difficoltà arriva quando si desidera consentire un letterale %o un _carattere nella stringa di ricerca, senza che agisca come un carattere jolly.

Quindi è qualcos'altro a cui prestare attenzione quando si combinano like e parametrizzazione.


6
+1 - questo mi sembra un buon approccio poiché tutta la concatenazione avviene nel database dopo che il segnaposto è stato sostituito e significa che è possibile utilizzare segnaposto con nome. Vale la pena ricordare che la sintassi sopra è per Oracle: in MySQL la sintassi è LIKE CONCAT('%', :something, '%'). Riferimento: stackoverflow.com/a/661207/201648
Aaron Newton

1
Questo non ha funzionato esattamente per me, ma mi ha portato sulla strada giusta. Ho dovuto fare LIKE '%': qualcosa '%' perché funzionasse.
Christopher Smit

so che questo è fuori tema ma sono stato in grado di eseguire l'iniezione sql anche utilizzando questa dichiarazione, perché?
Thiago Dias

Questo non ha funzionato per me, l'ho anche testato con il comando SQL SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )questo mi avrebbe dato un errore.
Luzan Baral

@AaronNewton and it means named placeholders can be used. Com'è anche un problema con i segnaposto con nome quando si concatena in PHP? Ovviamente la concatenazione in PHP supporta sia nominativi che posizionali e più portabili in quanto è possibile utilizzare la stessa query per qualsiasi database. Io non capisco il motivo per cui così tante persone pensano che ci sia alcuna differenza tra i segnaposto di nome e di posizione.
Il tuo buon senso

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
C'è qualche vantaggio nell'usarlo rispetto alla risposta accettata? L'utilizzo bindValueprotegge dagli attacchi di iniezione? La risposta accettata fondamentalmente nega il valore dell'utilizzo di ?segnaposto concatenando la stringa di ricerca in modo che %piaccia ai vecchi tempi.
felwithe

Qual è lo scopo di utilizzare la negazione prima di $ query-> rowCount () == 0? Ha davvero senso?
ssi-anik

14

Puoi anche provare questo. Affronto un problema simile ma ho ottenuto risultati dopo la ricerca.

$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);

Ho modificato il tuo post per inserire il codice in un blocco di codice: puoi leggere ulteriori informazioni sulla formattazione del post su stackoverflow.com/help/formatting . Qualche altro utente ha scelto di downvote la tua risposta senza lasciare un commento, quindi non sono sicuro della causa del downvote.
josliber

2
Ripeto, non ho votato la tua domanda; qualcun altro downvoted.
josliber

3

Funziona:

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

2

L'ho preso da php delusions

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

E per me funziona, molto semplice. Come dice lui, devi "preparare prima il nostro letterale completo" prima di inviarlo alla query


0

PDO sfugge a "%" (può portare a sql injection) : l'uso del codice precedente darà i risultati desiderati quando si cerca di abbinare stringhe parziali MA se un visitatore digita il carattere "%" otterrai comunque risultati anche se non lo fai non avere nulla memorizzato nel database (potrebbe portare a iniezioni sql)

Ho provato molte varianti, tutte con lo stesso risultato che PDO sfugge a "%" portando risultati di ricerca indesiderati / non stimolati.

Ho pensato che valesse la pena condividere se qualcuno ha trovato una parola attorno ad essa, per favore condividila


1
Questo è da manuale: us3.php.net/manual/en/pdo.prepared-statements.php Questo è un altro post dove sul tema: stackoverflow.com/questions/22030451/... mi owuld piace molto conoscere la vostra opinione su questo problema.
Ozkar R,

1
Possibile soluzione (non testato) Usa CONCAT , come: $ sql = “SELECT item_title FROM item WHERE item_title LIKE CONCAT ('%',?, '%')”; Riferimento: blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard
Ozkar R

3
DOP non sfugge%. È il tuo codice che lo fa male. Per la soluzione dovresti leggere le risposte già fornite qui
Il tuo buon senso,

Grazie per i tuoi suggerimenti. Ad ogni modo il codice testato era il codice del manuale, utilizzando il segnaposto per evitare l'iniezione SQL, sto ancora ottenendo lo stesso risultato Esempio # 6 L'uso non valido del segnaposto PDO fa l'escape% utilizzando il codice sopra, non il mio codice. Sono nuovo nel forum e potrei non capire come funziona il processo di commento, post e reputazione qui, lo terrò a mente per il mio prossimo, perché in base al commento precedente hai bisogno di reputazione per aiutare gli altri o fare commenti. Grazie.
Ozkar R,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.