code up

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

MySQL LIKE用の文字列エスケープ(\: backslash, %: percentage, _: underscore)

この方法を書いてる人を見つけられなかったので、正しいかは不明。utf8mb4_unicode_ci(あるいはutf8_unicode_ci)の影響かと思われる。関連しそうなバグレポート

  • MySQLデータベース: 5.5.21
  • getSearchStringEscape: \
  • sql_mode: TRADITIONAL
  • JDBCドライバのバージョン: 5.1.23
  • データベースの文字コード: utf8mb4
  • Javaのバージョン: 7

尚、検索にはPreparedStatementを使っている。

LIKE検索時に、パーセント(%)やアンダースコア(_)、あるいはバックスラッシュ、円マーク(\)を検索対象にしたい場合、呼び出し元(今回の場合はJava側)でエスケープする必要がある。

%_の置換はあちこちで見かけたが、この\の置換方法だけはうまくいかなかった。よく見かける'\\'(Javaだと"\\\\")を'\\\\'(同"\\\\\\\\")に変換する方法は場合によってダメであった。ワイルドカードとしての'%'の後にエスケープした'%'(つまり'\%')が続く場合とか。

色々試行錯誤した結果MySQLのバグっぽいcollate utf8mb4_unicode_ci like ?のようにunicode_ciで検索するときに問題発生。

少し強引な方法だけど下記でうまくいってそう。ただしunicode_ci(utf8mb4_unicode_ci, utf8_unicode_ci等)限定!

utf8mb4_general_ci, utf8_general_ciでは試してないけど普通に'\''\\'に変換すればよさげ。

public static String escape(String value) {
	return value == null ? null : String.format("%%%s%%", value.replaceAll("\\\\", "\")
			.replaceAll("%", "\\\\%").replaceAll("_", "\\\\_"));
}
select * from foo where bar like ?

というようなSQLに対して、

ps.setString(1, escape(value));

というような感じで呼び出す。

関連記事
タグ:Java MySQL
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。