2017/9/1
@Kilisameさんにご指摘いただき記事を修正しました。ご指摘いただきありがとうございました。
この記事で知れること
- エスケープ処理の例
- Javaのサンプルコード
注意
使用するDBによってエスケープしなければいけない記号は変わりますので注意して下さい。
今回はMariaDBを使用する場合のサンプルです。
解説
このような「商品リスト」テーブルがあるとします。
商品ID | 商品名 |
---|---|
1 | コーラ |
2 | オレンジ100% |
3 | 牛乳 |
4 | りんご100% |
5 | 牛乳_低脂肪 |
6 | オレンジ100個分ジュース |
7 | りんご100個分ジュース |
DBにinsertするSQL文はこちらです。
insert into 商品リスト (商品ID, 商品名) values ('1', 'コーラ'),
('2', 'オレンジ100%'),
('3', '牛乳'),
('4', 'りんご100%'),
('5', '牛乳_低脂肪'),
('6', 'オレンジ100個分ジュース'),
('7','りんご100個分ジュース');
この「商品リスト」テーブルに対して、部分一致検索をするSQL文はこちらです。
【1】「牛乳」で部分一致
select 商品ID, 商品名 from 商品リスト where 商品名 like '%牛乳%';
【2】「100%」で部分一致
select 商品ID, 商品名 from 商品リスト where 商品名 like '%100\%%';
結果
商品ID | 商品名 |
---|---|
2 | オレンジ100% |
4 | りんご100% |
【3】「_低脂肪」で部分一致
select 商品ID, 商品名 from 商品リスト where 商品名 like '%\_低脂肪%';
結果
商品ID | 商品名 |
---|---|
5 | 牛乳_低脂肪 |
「%」「_」記号は、DBにとって特別な意味を持ちますので、【2】【3】のようにエスケープ記号「\」を前につけないと、意図した部分一致検索ができません。
試しに、エスケープ記号を付けずにLIKE検索してみると、
【4】
select 商品ID, 商品名 from 商品リスト where 商品名 like '%100%%';
結果
商品ID | 商品名 |
---|---|
2 | オレンジ100% |
4 | りんご100% |
6 | オレンジ100個分ジュース |
7 | りんご100個分ジュース |
よって、アプリケーションで検索処理を実装したい場合は、検索対象ワードに対してエスケープ処理を行わなければいけません。
サンプルコード
public void getName(String word){
Connection con = null;
String sql = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
con = this.getConnection();
sql = "select 商品名 from 商品リスト where 商品名 like ?";
ps = con.prepareStatement(sql);
ps.setString(1, "%" +this.escape(word) + "%");
rs = ps.executeQuery();
rs.close();
ps.close();
}finally{
if(con != null){
con.close();
}
}
}
public String escape(String before){
StringBuilder after = new StringBuilder();
String esSymbol = "\";
char es1 = '_';
char es2 = '%';
for (int i = 0; i < before.length(); i++) {
if (before.charAt(i) == es1 || before.charAt(i) == es2) {
after.append(esSymbol);
after.append(String.valueOf(before.charAt(i)));
continue;
}
after.append(String.valueOf(before.charAt(i)));
}
return after.toString();
}