Como faço para criar uma consulta parametrizada PDO com uma instrução LIKE?

107

Aqui está minha tentativa:

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

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

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

Respostas:

124

Descobri logo depois de postar:

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

while ($results = $query->fetch())
{
    echo $results['column'];
}
Andrew G. Johnson
fonte
1
@Andrew: e se múltiplos likeforem usados? como o array de execução deve ser executado em ordem?
logan
obrigado. teve um problema semelhante com csharp + Mysql + ODBC usando como se não retornasse nenhuma linha usando "select * from table where column like '%?%';" mas irei se eu fizer como você fez "select * from table where column like?;" e defina a string de parâmetro assim: string frag = $ "% {searchFragment}%"; em seguida, use frag para o valor do parâmetro. Estranho
sdjuan
2
O PDO deve escapar dessa% na chamada de execução. A resposta de Kaqai é melhor
Peter Bagnall
Parece interessante notar que a principal nota de contribuição do usuário na página de documentação PDOStatement :: bindParam oferece uma abordagem diferente: Adicione o (s) sinal (is) de porcentagem à variável antes de vinculá-la.
Dan Robinson,
Dê uma olhada na solução de gavin, retirada da página Your Common Sense, perto do final deste tópico. Simples. Lógico.
RationalRabbit
85

Para aqueles que usam parâmetros nomeados, veja como usar LIKEcom %correspondência parcial para bancos de dados MySQL :

WHERE nome_da_coluna LIKE CONCAT ('%',: cadeia perigosa, '%')

onde está o parâmetro nomeado :dangerousstring.

Em outras palavras, use %sinais explicitamente sem escape em sua própria consulta que são separados e definitivamente não são a entrada do usuário.

Editar: a sintaxe de concatenação para bancos de dados Oracle usa o operador de concatenação:, ||então ele simplesmente se tornará:

WHERE column_name LIKE '%' || : corda perigosa || '%'

No entanto, existem ressalvas, pois @bobince menciona aqui que:

A dificuldade surge quando você deseja permitir um literal %ou _caractere na string de pesquisa, sem que ele atue como um curinga.

Portanto, isso é outra coisa a se observar ao combinar curtir e parametrização.

Kzqai
fonte
6
+1 - parece uma boa abordagem para mim, já que toda a concatenação acontece no banco de dados depois que o marcador de posição foi substituído, e isso significa que marcadores de posição nomeados podem ser usados. É importante mencionar que a sintaxe acima é para Oracle - no MySQL a sintaxe é LIKE CONCAT('%', :something, '%'). Referência: stackoverflow.com/a/661207/201648
Aaron Newton
1
Isso não funcionou exatamente para mim, mas me colocou no caminho certo. Eu tive que fazer LIKE '%': algo '%' para funcionar.
Christopher Smit de
Eu sei que isso é fora do tópico, mas fui capaz de executar injeção de sql mesmo usando esta instrução, por quê?
Thiago Dias
Isso não funcionou para mim, também testei com o comando SQL SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )que me daria um erro.
Luzan Baral
@AaronNewton and it means named placeholders can be used. Como é mesmo um problema com espaços reservados nomeados quando você concatena em PHP? Obviamente, a concatenação em PHP oferece suporte a nomes e posições e é mais portátil, pois você pode usar a mesma consulta para qualquer banco de dados. Eu realmente não entendo por que tantas pessoas pensam que há alguma diferença entre marcadores de posição nomeados e posicionais.
Seu senso comum
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
fonte
1
Há alguma vantagem em usar isso em relação à resposta aceita? O uso bindValueprotege contra ataques de injeção? A resposta aceita basicamente nega o valor de usar ?marcadores de posição, concatenando a string de pesquisa para %like nos dias de antigamente.
felwithe
Qual é o ponto de usar negação antes de $ query-> rowCount () == 0? Isso realmente faz sentido?
ssi-anik
14

Você também pode tentar este. Eu enfrento problema semelhante, mas obtive resultado após pesquisa.

$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
fonte
Eu editei sua postagem para colocar o código em um bloco de código - você pode ler mais sobre a formatação de postagem em stackoverflow.com/help/formatting . Outro usuário optou por votar negativamente em sua resposta sem deixar um comentário, então não tenho certeza sobre a causa da votação negativa.
josliber
2
Para repetir, eu não votei na sua pergunta; outra pessoa votou negativamente.
josliber
3

Isso funciona:

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

Eu peguei isso de ilusões php

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

E funciona para mim, muito simples. Como ele diz, você deve "preparar nosso literal completo primeiro" antes de enviá-lo para a consulta

gavin
fonte
0

O PDO escapa "%" (pode levar à injeção de sql) : O uso do código anterior fornecerá os resultados desejados ao procurar strings parciais, MAS se um visitante digitar o caractere "%", você ainda obterá resultados mesmo que não Não tenho nada armazenado na base de dados (pode levar a injeções de sql)

Eu tentei muitas variações, todas com o mesmo resultado O PDO está escapando de "%" levando a resultados de pesquisa indesejados / não excitados.

Achei que valeria a pena compartilhar se alguém encontrou uma palavra sobre isso, compartilhe

Ozkar R
fonte
1
Este é do Manual: us3.php.net/manual/en/pdo.prepared-statements.php Este é outro post sobre o assunto: stackoverflow.com/questions/22030451/… Eu realmente gostaria de saber sua opinião sobre este issu.
Ozkar R
1
Solução possível (não testada) Use CONCAT , como: $ sql = “SELECT item_title FROM item WHERE item_title LIKE CONCAT ('%',?, '%')”; Referência: blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard
Ozkar R
3
O PDO não escapa%. É o seu código que faz isso errado. Para a solução, você deve ler as respostas já fornecidas aqui
Seu senso comum
Obrigado por suas sugestões. De qualquer forma, o código testado foi o código do manual, usando espaço reservado para evitar injeção de SQL, ainda estou obtendo o mesmo resultado Exemplo # 6 O uso inválido do espaço reservado PDO escapa% usando o código acima, não meu código. Sou novo no fórum e posso não entender como funciona o processo de comentário, postagem e reputação aqui, vou mantê-lo em mente no próximo, porque com base no comentário anterior você precisa de reputação para ajudar outras pessoas ou fazer comentários. obrigado.
Ozkar R