使用LIKE时,使用Java清理SQL输入

时间:2013-10-15 16:40:26

标签: java sql prepared-statement indexing sql-like

我们都知道在Java中你应该使用PreparedStatments来避免安全漏洞。

但是,我注意到当使用 LIKE 语句进行“开始”搜索时,PreparedStatments会导致性能问题。因为语句是在没有值的情况下编译的,所以驱动程序必须假设通配符可以在任何地方,包括开头,因此它会跳过该列上的任何索引。但是如果使用 LIKE 值作为文字编译语句,它会看到它可以使用列上的索引,直到通配符和查询执行良好。

//safe, but prepared statement can't use index on MYCOL
String userInput = "myval%";
statement = conn.prepareStatement("SELECT * FROM MYTABLE WHERE MYCOL LIKE ?");
statement.setString(1, userInput);
rs = statement.executeQuery();


//can use index on MYCOL, but is not safe
statement = conn.createStatement();
rs = statement.executeQuery("SELECT * FROM MYTABLE WHERE MYCOL LIKE '"+userInput+"'");

那么如何在保持索引的同时避免安全漏洞呢?我假设我将不得不尝试清理输入而不是使用PreparedStatement - 如果是这样,是否存在正确的库?或者是否有相同的java.sql或(oracle)数据库提示方式告诉准备好的语句它能够在值上使用索引吗?

2 个答案:

答案 0 :(得分:1)

您是否考虑过在数据库端创建stored_procedure?这样您就可以将stored_procedure名称和类似字符串作为参数发送到数据库,并使用java端的结果集。这样,您就知道查询将使用您正在处理的表的索引。

答案 1 :(得分:1)

创建一个sql函数来执行此操作,或使用第二种方法只是转义字符(' - >> ''

String userInput="IBM";
statement = conn.createStatement();
    rs = statement.executeQuery("SELECT * FROM MYTABLE WHERE MYCOL LIKE '"+userInput.replaceAll("'","''")+"%'");