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)データベースヒントの方法はありますか?