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();
ssn
fonte

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 + "%");
BalusC
fonte
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 + "%'");
O lobo do casamento
fonte
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.

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

Experimente isso.

Faiz
fonte
1
String fname = "Sam\u0025";

PreparedStatement ps= conn.prepareStatement("SELECT * FROM Users WHERE User_FirstName LIKE ? ");

ps.setString(1, fname);
Ram Kumar
fonte
2
Você poderia elaborar a resposta em vez de apenas dar a resposta? Veja: stackoverflow.com/help/how-to-answer
Edwin
-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
mahesh dhote
fonte
não é seguro, use gentilmente instruções preparadas com parâmetros.
Durgesh Kumar 23/09/19