21
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LIKE検索時にエスケープ処理をする

Last updated at Posted at 2017-08-30

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();
}
21
11
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?