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'];
}

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'];
}

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.


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';
}

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

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, '%')

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


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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.