Usando curinga "like" na instrução preparada


176

Estou usando instruções preparadas para executar consultas ao banco de dados mysql. E quero implementar uma funcionalidade de pesquisa com base em uma espécie de palavra-chave.

Para isso eu preciso usar a LIKEpalavra-chave, isso eu sei. E eu também já usei instruções preparadas antes, mas não sei como usá-lo LIKEporque, a partir do código a seguir, onde eu adicionaria o 'keyword%'?

Posso usá-lo diretamente no pstmt.setString(1, notes)como (1, notes+"%")ou algo assim. Vejo muitas postagens sobre isso na Web, mas não há uma boa resposta em nenhum lugar.

PreparedStatement pstmt = con.prepareStatement(
      "SELECT * FROM analysis WHERE notes like ?");
pstmt.setString(1, notes);
ResultSet rs = pstmt.executeQuery();

Respostas:


281

Você precisa configurá-lo no próprio valor, não na sequência SQL da instrução preparada.

Portanto, isso deve ser feito para uma correspondência de prefixo:

notes = notes
    .replace("!", "!!")
    .replace("%", "!%")
    .replace("_", "!_")
    .replace("[", "![");
PreparedStatement pstmt = con.prepareStatement(
        "SELECT * FROM analysis WHERE notes LIKE ? ESCAPE '!'");
pstmt.setString(1, notes + "%");

ou uma correspondência de sufixo:

pstmt.setString(1, "%" + notes);

ou uma correspondência global:

pstmt.setString(1, "%" + notes + "%");

18
+1 O OP pode "configurá-lo" no SQL - como por ... LIKE '%' || ? || '%'ou similar - mas isso é muito menos flexível.
Pilcrow

como faço para fazê-lo com o modo NÃO CASE SENSITIVE? :)
Alpha Gabriel V. Timbol

2
Não case-sensitive ainda pode usar WHERE UPPER(?) LIKE UPPER(?)quando se utilizapstmt.setString(2, "%" + notes + "%")
Zig

1
@ Alain: Obrigado. Apenas imaginando, isso se aplica a todos os RDBMS de que o mundo está ciente? Talvez '%' || ? || '%'como mencionado no primeiro comentário tenha sido melhor, afinal? Não tenho a oportunidade de experimentar agora.
BalusC

2
@BalusC isso se aplica ao MSSQL, Postgres e MySQL nos meus testes. A String sendo transformada em parâmetro é interpretada como uma mistura de dados e instruções de controle. A concatenação do SQL ocorre antes de ser interpretada e preserva a vulnerabilidade. O IEEE Center for Secure Design recomenda separar estritamente as instruções de controle e dados e nunca processar instruções de controle recebidas de fontes não confiáveis .
Alain O'Dea

28

Codifique-o assim:

PreparedStatement pstmt = con.prepareStatement(
    "SELECT * FROM analysis WHERE notes like ?");
pstmt.setString(1, notes + "%");`

Certifique-se de que você NÃO incluem as aspas '' como abaixo como eles vão causar uma exceção.

pstmt.setString(1,"'%"+ notes + "%'");

1
Embora pareça que alguém não se depara com essa suposição, na verdade é muito válido, especialmente quando se trabalha com a Oracle. Obrigado por apontar!
ASGs

5

podemos fazer isso de forma simples, usando a função CONCATE SQL.

PreparedStatement pstmt = con.prepareStatement(
      "SELECT * FROM analysis WHERE notes like CONCAT( '%',?,'%')";
pstmt.setString(1, notes);
ResultSet rs = pstmt.executeQuery();

isso funciona perfeitamente para o meu caso.


4
PreparedStatement ps = cn.prepareStatement("Select * from Users where User_FirstName LIKE ?");
ps.setString(1, name + '%');

Experimente isso.



-13
String query="select * from test1 where "+selected+" like '%"+SelectedStr+"%';";


PreparedStatement preparedStatement=con.prepareStatement(query);


// where seleced and SelectedStr are String Variables in my program

não é seguro, use gentilmente instruções preparadas com parâmetros.
Durgesh Kumar 23/09/19
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.