SQLで特定の文字を含むデータを検索する方法|LIKE句の完全ガイド

データベース・SQL
スポンサーリンク
  1. 「〇〇を含む」データを探したい!
  2. LIKE句の基本を理解しよう
    1. LIKE句とは
    2. 基本構文
    3. ワイルドカードの種類
  3. 基本的な検索パターン
    1. 前方一致検索(〇〇で始まる)
    2. 後方一致検索(〇〇で終わる)
    3. 部分一致検索(〇〇を含む)
    4. 任意の1文字を表す検索
    5. 複数のワイルドカードを組み合わせる
  4. NOT LIKEで「含まない」を検索
    1. 基本的な使い方
    2. 複数の条件で除外
    3. 正規ユーザーのみ抽出
  5. 複数の条件を組み合わせる
    1. OR条件で複数パターンを検索
    2. AND条件で絞り込み
    3. IN句との併用は不可
  6. 大文字小文字の区別
    1. MySQLの場合
    2. PostgreSQLの場合
    3. SQL Serverの場合
  7. エスケープ処理:特殊文字を検索する
    1. 問題のあるケース
    2. エスケープ文字を使う
    3. ESCAPE句を使う方法
    4. アンダースコアのエスケープ
  8. パフォーマンスの考慮
    1. インデックスが効かないパターン
    2. 対策方法
    3. 大量データでの注意点
  9. 正規表現を使った高度な検索
    1. MySQLの場合
    2. PostgreSQLの場合
    3. 正規表現の主なパターン
  10. 実践的な使用例
    1. 例1:メールアドレスの形式チェック
    2. 例2:郵便番号の検索
    3. 例3:商品コードの検索
    4. 例4:禁止ワードのチェック
    5. 例5:ファイル拡張子での絞り込み
    6. 例6:バージョン番号の検索
    7. 例7:日本語の部分一致
  11. よくある質問と回答
    1. Q1:複数の単語を全て含むデータを検索するには?
    2. Q2:LIKEとINを組み合わせられない?
    3. Q3:NULLはLIKEで検索できる?
    4. Q4:空文字列は%にマッチする?
    5. Q5:LIKE検索が遅い時の対処法は?
    6. Q6:日本語の検索で文字化けする
  12. LIKE検索のベストプラクティス
    1. 1. 可能な限り前方一致にする
    2. 2. 複数条件で絞り込んでから検索
    3. 3. 大量データでは件数制限を設ける
    4. 4. パラメータ化を使う
    5. 5. ワイルドカードのエスケープを忘れずに
  13. まとめ:LIKE句を使いこなそう

「〇〇を含む」データを探したい!

データベースを使っていると、「田中という名字の人を全員探したい」「.comで終わるメールアドレスを抽出したい」といった、特定の文字列を含むデータを検索したくなることがよくあります。

完全一致ならWHERE name = '田中太郎'と簡単に書けますが、「田中」を含む全ての名前を探すにはどうすればいいのでしょうか。「田中太郎」も「田中花子」も「佐藤田中」も全て見つけたいですよね。

そんな時に使うのが、LIKE句(ライク句)です。LIKE句を使えば、「○○で始まる」「○○を含む」「○○で終わる」といった、柔軟な文字列検索ができるようになります。

この記事では、SQLで特定の文字を含むデータを検索する方法を、基本から応用まで分かりやすく解説していきます。実務でよく使う検索パターンも豊富に紹介しますので、ぜひ参考にしてください。

LIKE句の基本を理解しよう

まずは、LIKE句の基本的な使い方から見ていきましょう。

LIKE句とは

LIKE句は、パターンマッチング(文字列の部分一致)を行うためのSQL構文です。「ライク」は英語で「〜のような」という意味で、「このパターンのような文字列」を探すイメージです。

通常の等号(=)は完全一致しか検索できませんが、LIKE句を使えば「似ている文字列」を探せます。

基本構文

SELECT column_name
FROM table_name
WHERE column_name LIKE 'pattern';

patternの部分に、検索したい文字列のパターンを指定します。

実行例

SELECT name, email
FROM customers
WHERE name LIKE '田中%';

「田中」で始まる名前を持つ顧客を全て取得します。

ワイルドカードの種類

LIKE句では、「ワイルドカード」という特殊な記号を使ってパターンを指定します。ワイルドカードは「何でも当てはまる」という意味の記号です。

%(パーセント)
0文字以上の任意の文字列を表します。何文字でもマッチします。

_(アンダースコア)
任意の1文字を表します。必ず1文字だけマッチします。

この2つを覚えておけば、ほとんどの検索ができます。

基本的な検索パターン

よく使う検索パターンを順番に見ていきましょう。

前方一致検索(〇〇で始まる)

「特定の文字で始まるデータ」を探す方法です。

パターン

WHERE column_name LIKE '検索文字%'

使用例

-- 「田中」で始まる名前を検索
SELECT name FROM customers
WHERE name LIKE '田中%';

検索結果の例

田中太郎
田中花子
田中一郎

「田中」の後ろに何が続いても、全てヒットします。

実用例:都道府県名での絞り込み

-- 「東京都」で始まる住所を検索
SELECT customer_name, address
FROM customers
WHERE address LIKE '東京都%';

「東京都渋谷区〜」「東京都新宿区〜」などが抽出されます。

後方一致検索(〇〇で終わる)

「特定の文字で終わるデータ」を探す方法です。

パターン

WHERE column_name LIKE '%検索文字'

使用例

-- 「.com」で終わるメールアドレスを検索
SELECT name, email
FROM customers
WHERE email LIKE '%.com';

検索結果の例

test@example.com
user@sample.com
admin@company.com

実用例:特定のドメインを除外

-- .co.jpで終わるメールアドレス以外を検索
SELECT name, email
FROM customers
WHERE email NOT LIKE '%.co.jp';

部分一致検索(〇〇を含む)

「特定の文字をどこかに含むデータ」を探す方法です。最もよく使うパターンです。

パターン

WHERE column_name LIKE '%検索文字%'

使用例

-- 「山」という字を含む名前を検索
SELECT name FROM customers
WHERE name LIKE '%山%';

検索結果の例

山田太郎
小山花子
山本一郎
佐藤山田

前でも後ろでも中間でも、「山」が含まれていれば全てヒットします。

実用例:商品名での検索

-- 「ノート」を含む商品を検索
SELECT product_name, price
FROM products
WHERE product_name LIKE '%ノート%';

「ノートパソコン」「ノート(文具)」「A4ノート」など、全てヒットします。

任意の1文字を表す検索

アンダースコア(_)を使うと、任意の1文字にマッチします。

パターン

WHERE column_name LIKE 'パターン_パターン'

使用例

-- 「A」の後ろに1文字、その後「B」が続くパターン
SELECT code FROM products
WHERE code LIKE 'A_B';

検索結果の例

A1B  -- マッチ
A9B  -- マッチ
AXB  -- マッチ
AB   -- マッチしない(文字が足りない)
A12B -- マッチしない(文字が多い)

実用例:郵便番号の検索

-- 100-00XX形式の郵便番号を検索(XXは任意の2桁)
SELECT customer_name, postal_code
FROM customers
WHERE postal_code LIKE '100-00__';

「100-0001」「100-0012」などがヒットします。

複数のワイルドカードを組み合わせる

%と_を組み合わせて、より複雑なパターンも指定できます。

使用例

-- 2文字目が「田」で、5文字以上の名前
SELECT name FROM customers
WHERE name LIKE '_田%'
AND LENGTH(name) >= 5;

使用例:電話番号のパターン

-- 090または080で始まる携帯番号
SELECT customer_name, phone
FROM customers
WHERE phone LIKE '090%' OR phone LIKE '080%';

NOT LIKEで「含まない」を検索

特定の文字を含まないデータを探す時は、NOT LIKEを使います。

基本的な使い方

パターン

WHERE column_name NOT LIKE 'pattern'

使用例

-- 「test」を含まないメールアドレスを検索
SELECT name, email
FROM customers
WHERE email NOT LIKE '%test%';

テストアカウントを除外したい時などに便利です。

複数の条件で除外

-- 特定のドメインを全て除外
SELECT name, email
FROM customers
WHERE email NOT LIKE '%@test.com'
AND email NOT LIKE '%@example.com'
AND email NOT LIKE '%@dummy.com';

正規ユーザーのみ抽出

-- 名前に「テスト」「test」「ダミー」を含まないユーザー
SELECT user_id, username
FROM users
WHERE username NOT LIKE '%テスト%'
AND username NOT LIKE '%test%'
AND username NOT LIKE '%ダミー%'
AND username NOT LIKE '%dummy%';

開発環境から本番データを抽出する時に役立ちます。

複数の条件を組み合わせる

LIKE句は、ANDやORと組み合わせて使えます。

OR条件で複数パターンを検索

使用例:複数の名字を検索

SELECT name, email
FROM customers
WHERE name LIKE '田中%'
OR name LIKE '佐藤%'
OR name LIKE '鈴木%';

日本で最も多い3つの名字を持つ顧客を検索します。

使用例:複数の都道府県

SELECT customer_name, address
FROM customers
WHERE address LIKE '東京都%'
OR address LIKE '神奈川県%'
OR address LIKE '千葉県%'
OR address LIKE '埼玉県%';

首都圏の顧客を抽出できます。

AND条件で絞り込み

-- 「株式会社」を含み、かつ「システム」も含む会社名
SELECT company_name
FROM companies
WHERE company_name LIKE '%株式会社%'
AND company_name LIKE '%システム%';

「株式会社ABCシステム」「システム開発株式会社」などがヒットします。

IN句との併用は不可

残念ながら、LIKEとINは直接組み合わせられません。

これはできない

-- エラーになる
WHERE name LIKE IN ('田中%', '佐藤%');

代わりにORを使う

WHERE name LIKE '田中%'
OR name LIKE '佐藤%';

または、REGEXP(後述)を使う方法もあります。

大文字小文字の区別

データベースによって、大文字小文字の区別の扱いが異なります。

MySQLの場合

デフォルトでは大文字小文字を区別しません。

-- MySQLではこれらは同じ結果
WHERE name LIKE '%yamada%'
WHERE name LIKE '%YAMADA%'
WHERE name LIKE '%Yamada%'

全て「yamada」「YAMADA」「Yamada」にマッチします。

区別したい場合

-- バイナリ比較で区別する
WHERE name LIKE BINARY '%Yamada%'

または、照合順序(COLLATE)を指定します。

WHERE name LIKE '%Yamada%' COLLATE utf8mb4_bin

PostgreSQLの場合

デフォルトでは大文字小文字を区別します。

-- これは「Yamada」にしかマッチしない
WHERE name LIKE '%Yamada%'

区別しない場合

-- ILIKEを使う(PostgreSQL独自)
WHERE name ILIKE '%yamada%'

ILIKEは、大文字小文字を区別せずに検索します。

SQL Serverの場合

照合順序によって決まります。デフォルトでは区別しないことが多いです。

-- 照合順序を指定して区別
WHERE name LIKE '%Yamada%' COLLATE Latin1_General_CS_AS
-- CS = Case Sensitive(大文字小文字を区別)

エスケープ処理:特殊文字を検索する

%や_そのものを検索したい場合、エスケープ処理が必要です。

問題のあるケース

-- これでは意図した結果にならない
SELECT product_name
FROM products
WHERE product_name LIKE '%50%';

「50%OFF」という文字列を探しているつもりでも、%がワイルドカードとして解釈されてしまいます。

エスケープ文字を使う

バックスラッシュ(\)を使ってエスケープします。

-- %記号そのものを検索
SELECT product_name
FROM products
WHERE product_name LIKE '%50\%%';

「50%OFF」「割引50%」などが正しく検索されます。

ESCAPE句を使う方法

-- 任意の文字をエスケープ文字として指定
SELECT product_name
FROM products
WHERE product_name LIKE '%50#%%' ESCAPE '#';

#をエスケープ文字として指定すると、#%が%そのものを表します。

アンダースコアのエスケープ

-- アンダースコアそのものを検索
SELECT file_name
FROM files
WHERE file_name LIKE '%test\_%';

「test_file.txt」「test_data.csv」などがヒットします。

パフォーマンスの考慮

LIKE句は便利ですが、使い方によってはパフォーマンスが悪くなります。

インデックスが効かないパターン

前方一致はインデックスが効く

-- インデックスが使われる(高速)
WHERE name LIKE '田中%'

データベースは、インデックスを使って効率的に検索できます。

部分一致・後方一致はインデックスが効かない

-- インデックスが使われない(遅い)
WHERE name LIKE '%田中%'
WHERE name LIKE '%田中'

先頭にワイルドカードがあると、インデックスを活用できません。全件スキャンが発生するため、データ量が多いと非常に遅くなります。

対策方法

1. 全文検索インデックスを使う

-- MySQLの全文検索(FULLTEXT INDEX)
CREATE FULLTEXT INDEX idx_name ON customers(name);

-- 検索
SELECT * FROM customers
WHERE MATCH(name) AGAINST('田中' IN NATURAL LANGUAGE MODE);

部分一致でも高速に検索できます。

2. 前方一致に変更できないか検討
検索要件を見直して、前方一致で対応できないか考えましょう。

3. 別の検索方法を検討

  • 検索専用のカラムを追加
  • Elasticsearchなどの全文検索エンジンを使用
  • データベースの全文検索機能を活用

大量データでの注意点

-- 遅い:部分一致で100万件から検索
SELECT * FROM large_table
WHERE description LIKE '%キーワード%';

-- 速い:まず別の条件で絞り込んでから検索
SELECT * FROM large_table
WHERE category = 'electronics'  -- インデックスで高速に絞り込み
AND description LIKE '%キーワード%';  -- 絞り込まれたデータから検索

まずインデックスが効く条件で絞り込んでから、LIKE検索をすると効率的です。

正規表現を使った高度な検索

より複雑なパターンマッチングには、正規表現が使えます。

MySQLの場合

REGEXP演算子

-- 正規表現で検索(MySQL 8.0以降はREGEXP)
SELECT name FROM customers
WHERE name REGEXP '^(田中|佐藤|鈴木)';

「田中」「佐藤」「鈴木」で始まる名前を一度に検索できます。

使用例:電話番号の形式チェック

-- 090または080で始まる11桁の電話番号
SELECT phone FROM customers
WHERE phone REGEXP '^(090|080)[0-9]{8}$';

PostgreSQLの場合

~演算子

-- 正規表現で検索
SELECT name FROM customers
WHERE name ~ '^(田中|佐藤|鈴木)';

大文字小文字を区別しない

-- ~*演算子を使う
SELECT email FROM customers
WHERE email ~* '^[a-z0-9]+@example\.com$';

正規表現の主なパターン

パターン意味
^行の先頭^A(Aで始まる)
$行の末尾A$(Aで終わる)
.任意の1文字A.B(AとBの間に1文字)
*0回以上の繰り返しA*(Aが0回以上)
+1回以上の繰り返しA+(Aが1回以上)
?0回または1回A?(Aが0回か1回)
[abc]a、b、cのいずれか[0-9](0〜9の数字)
|または(A|B)(AまたはB)

実践的な使用例

実際のプロジェクトで役立つ、具体的な検索例を紹介します。

例1:メールアドレスの形式チェック

-- 基本的なメール形式をチェック
SELECT customer_id, email
FROM customers
WHERE email LIKE '%@%.%'
AND email NOT LIKE '%@%@%'  -- @が2つ以上ない
AND email NOT LIKE '% %';    -- スペースを含まない

例2:郵便番号の検索

-- 特定の地域の郵便番号(100-0000〜199-9999)
SELECT customer_name, postal_code, address
FROM customers
WHERE postal_code LIKE '1__-____';

例3:商品コードの検索

-- カテゴリコードが「A」で、年度が「24」の商品
SELECT product_code, product_name
FROM products
WHERE product_code LIKE 'A%-24-%';

「A-001-24-01」「A-025-24-12」などの形式にマッチします。

例4:禁止ワードのチェック

-- コメントに不適切な言葉が含まれていないかチェック
SELECT comment_id, user_id, comment_text
FROM comments
WHERE comment_text LIKE '%禁止ワード1%'
OR comment_text LIKE '%禁止ワード2%'
OR comment_text LIKE '%禁止ワード3%';

例5:ファイル拡張子での絞り込み

-- 画像ファイルのみ抽出
SELECT file_id, file_name, file_size
FROM uploaded_files
WHERE file_name LIKE '%.jpg'
OR file_name LIKE '%.jpeg'
OR file_name LIKE '%.png'
OR file_name LIKE '%.gif';

例6:バージョン番号の検索

-- バージョン2.xのデータを検索
SELECT software_name, version
FROM software_list
WHERE version LIKE '2.%';

「2.0」「2.1.5」「2.10.3」などがヒットします。

例7:日本語の部分一致

-- 「システム」を含む会社名(全角・半角両方)
SELECT company_id, company_name
FROM companies
WHERE company_name LIKE '%システム%'
OR company_name LIKE '%システム%';

全角カタカナと半角カタカナの両方に対応します。

よくある質問と回答

LIKE句の使用について、よくある質問をまとめました。

Q1:複数の単語を全て含むデータを検索するには?

AND条件を使います。

-- 「Python」と「Django」を両方含む
SELECT title, description
FROM articles
WHERE description LIKE '%Python%'
AND description LIKE '%Django%';

順序は問わず、両方含まれていればヒットします。

Q2:LIKEとINを組み合わせられない?

直接は組み合わせられませんが、ORで代用できます。

-- 複数パターンのいずれかにマッチ
WHERE name LIKE '田中%'
OR name LIKE '佐藤%'
OR name LIKE '鈴木%';

パターンが多い場合は、正規表現を検討しましょう。

Q3:NULLはLIKEで検索できる?

できません。NULLは特別な値なので、IS NULLを使う必要があります。

-- これは何もヒットしない
WHERE column_name LIKE '%'

-- NULLをチェックする正しい方法
WHERE column_name IS NULL

Q4:空文字列は%にマッチする?

はい、マッチします。

-- 空文字列もヒットする
WHERE name LIKE '%'

空文字列を除外したい場合は、追加の条件が必要です。

WHERE name LIKE '%'
AND name != '';

Q5:LIKE検索が遅い時の対処法は?

以下の方法を検討してください。

  1. 前方一致に変更(可能なら)
  2. 全文検索インデックスの作成
  3. 別の条件で先に絞り込み
  4. 検索専用カラムの追加
  5. 外部の全文検索エンジン使用(Elasticsearch等)

大量データでの部分一致検索は、どうしても遅くなりがちです。

Q6:日本語の検索で文字化けする

文字コードの問題かもしれません。

-- 接続時の文字コードを確認
SHOW VARIABLES LIKE 'character%';

-- UTF-8で統一されているか確認

テーブルの文字コードもUTF-8(utf8mb4)に統一しましょう。

LIKE検索のベストプラクティス

効果的にLIKE句を使うためのポイントをまとめます。

1. 可能な限り前方一致にする

-- 推奨:インデックスが効く
WHERE name LIKE '田中%'

-- 避ける:インデックスが効かない
WHERE name LIKE '%田中%'

検索要件を見直して、前方一致で対応できないか検討しましょう。

2. 複数条件で絞り込んでから検索

-- 良い例
WHERE category = 'books'        -- まずカテゴリで絞り込み
AND created_at >= '2024-01-01'  -- 日付でさらに絞り込み
AND title LIKE '%Python%';      -- 最後にLIKE検索

-- 悪い例
WHERE title LIKE '%Python%';    -- いきなり全件から検索

3. 大量データでは件数制限を設ける

-- 最大100件まで取得
SELECT * FROM articles
WHERE content LIKE '%keyword%'
LIMIT 100;

4. パラメータ化を使う

アプリケーションから実行する場合、SQLインジェクション対策としてパラメータ化を使います。

# Python + MySQLの例
query = "SELECT * FROM customers WHERE name LIKE %s"
params = (f'%{search_keyword}%',)
cursor.execute(query, params)

ユーザー入力をそのままSQL文に埋め込んではいけません。

5. ワイルドカードのエスケープを忘れずに

ユーザー入力に%や_が含まれる可能性がある場合、エスケープ処理が必要です。

# Pythonでのエスケープ例
def escape_like(value):
    return value.replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_')

search_term = escape_like(user_input)

まとめ:LIKE句を使いこなそう

SQLで特定の文字を含むデータを検索する方法について、理解が深まったでしょうか。

重要なポイントをおさらい

  1. LIKE句の基本:%(0文字以上)と_(1文字)のワイルドカード
  2. 3つの検索パターン:前方一致、後方一致、部分一致
  3. NOT LIKE:特定の文字を含まないデータの検索
  4. パフォーマンス:前方一致はインデックスが効く、部分一致は遅い
  5. エスケープ:%や_そのものを検索する時は\でエスケープ
  6. 正規表現:複雑なパターンはREGEXPやREGEXP_LIKEを使う

LIKE句は、データベース検索の基本中の基本です。以下のような場面で日常的に使います。

  • ユーザー検索(名前の部分一致)
  • 商品検索(商品名やキーワード)
  • ログ分析(エラーメッセージの検索)
  • データクレンジング(不正なデータの抽出)

ただし、パフォーマンスには注意が必要です。大量データで部分一致検索をする場合は、全文検索インデックスや専用の検索エンジンの導入も検討しましょう。

実務では、まず前方一致で解決できないか考え、どうしても部分一致が必要な場合のみ使う、という姿勢が大切です。適切に使い分けて、効率的なデータ検索を実現してくださいね!

コメント

タイトルとURLをコピーしました