SQLのLIKEとは ― %と_の使い方
SQLの
SQLのLIKEとは、文字列の一部が合う行を選ぶ条件
SQLのLIKEは、WHERE句で文字列の一部が合う行を選ぶための述語(条件を表す語)です。パターンの中では、%が0文字以上の任意の文字列に、_がちょうど1文字に一致します。
SELECT文のWHERE句は、=を使うと値がぴったり同じ行しか選べません。LIKEを使うと、USBで始まる商品やケーブルを含む商品のように、名前の一部で行を選べます。
SELECT 商品名 FROM 商品
WHERE 商品名 LIKE 'USB%'; -- USBで始まる商品名LIKEの右側に書く文字列を、パターンと呼びます。パターンの中の%と_は、どんな文字の代わりにもなる記号として働きます。
%と_の違いは、一致する文字の数
%は何文字にでも一致し、_はちょうど1文字だけに一致します。%は0文字でもよいので、%の位置に文字が無くても一致します。_はその位置に必ず1文字を求めるので、文字が足りなくても余っても一致しません。
LIKEは、パターンが文字列の全体に合うかを調べます。PostgreSQLの文書も、LIKEは常に文字列全体を対象にすると説明しています。そのため、ネット_はネットワークの先頭3文字に合っても、残りの2文字が余るので一致しません。
_が一致するのは、1バイトではなく1文字です。PostgreSQLの文字コードがUTF8のデータベースで確かめると、漢字の塾も1文字として_に一致しました。全角のUSBと半角のUSBは別の文字なので、互いに一致しません。
前方一致・後方一致・部分一致と、_で文字数を決める書き方
%をパターンのどこに置くかで、探し方が変わります。後ろに置けば前方一致、前に置けば後方一致、両側に置けば部分一致になります。_を並べると、その位置の文字数を決められます。
| 書き方 | パターンの | 一致する |
|---|---|---|
| 前方一致 | 'USB%' | USBケーブル・USBメモリ・USB-Cハブ |
| 後方一致 | '%ケーブル' | USBケーブル・LANケーブル・HDMIケーブル |
| 部分 | '%ケーブル%' | 上の |
| 文字数を | '___ケーブル' | USBケーブル・LANケーブル |
%も_も無いパターンは、文字列そのものを表します。PostgreSQLの文書は、この場合のLIKEは=と同じ働きをすると説明しています。LIKE 'マウス' は、商品名がちょうどマウスの行だけに一致します。
パターンを当てて、一致する行を確かめる
次の図では、8行の商品の表にLIKEのパターンを試せます。パターンを選ぶか入力すると、一致する行が光ります。ボタンで選べるパターンの結果は、PostgreSQLで実際に実行して確かめたものです。
SELECT 商品名 FROM 商品
WHERE 商品名 LIKE 'USB%';SELECT 商品名 FROM 商品
WHERE 商品名 LIKE '%ケーブル';SELECT 商品名 FROM 商品
WHERE 商品名 LIKE '%ケーブル%';SELECT 商品名 FROM 商品
WHERE 商品名 LIKE '___ケーブル';SELECT 商品名 FROM 商品
WHERE 商品名 LIKE 'マウス%';SELECT 商品名 FROM 商品
WHERE 商品名 LIKE 'マウス_';SELECT 商品名 FROM 商品
WHERE 商品名 LIKE 'マウス';SELECT 商品名 FROM 商品
WHERE 商品名 LIKE '_SB%';| 番号 | 商品名 | 一致 |
|---|---|---|
| 1 | USBケーブル | 一致 |
| 2 | USBメモリ | 一致 |
| 3 | LANケーブル | - |
| 4 | HDMIケーブル | - |
| 5 | ケーブルカバー | - |
| 6 | マウス | - |
| 7 | マウスパッド | - |
| 8 | USB-Cハブ | 一致 |
'マウス%' と 'マウス_' を比べると、%と_の違いが分かります。%は0文字にも一致するので、マウスも一致します。_は必ず1文字を求めるので、マウスもマウスパッドも一致しません。
NOT LIKEと、%や_そのものを探すESCAPE
NOT LIKEは、パターンに合わない行を選ぶ
NOT LIKEは、LIKEの結果を逆にした条件です。NOT LIKE '%ケーブル%' は、ケーブルを含まない商品名の行を選びます。前の節の表では、USBメモリ・マウス・マウスパッド・USB-Cハブの4行が残ります。
列の値がNULLの行は、LIKEでもNOT LIKEでも選ばれません。NULLにLIKEを使うと、結果が真でも偽でもないUNKNOWNになるためです。WHERE句はUNKNOWNの行を結果に残さないので、NULLの行も含めたいときはOR 列 IS NULLを足します。
ESCAPEで、%や_を記号ではなく文字として扱う
10%オフのように、%の文字そのものを探したい場面があります。LIKE '10%' と書くと、%が記号として働き、10で始まる名前が全部一致します。クーポンの表で確かめると、次のようになります。
-- クーポン名:10%オフ、100円オフ、10個セット
WHERE クーポン名 LIKE '10%'; -- 3行とも一致
WHERE クーポン名 LIKE '10!%%' ESCAPE '!'; -- 10%オフだけESCAPEで決めた文字の直後にある%や_は、記号ではなく普通の文字として扱われます。この文字をエスケープ文字と呼びます。上の例では!がエスケープ文字なので、!%は%の文字に、最後の%は記号として残りの文字列に一致します。!そのものを探すときは、!!と2つ重ねます。
ESCAPEを書かないときの扱いは、規格と製品で違います。SQLの規格では、ESCAPEを省くとエスケープ文字はありません。PostgreSQLは、省いたときにバックスラッシュをエスケープ文字として扱います。MySQLも同じですが、NO_BACKSLASH_ESCAPESというSQLモードが有効なときはエスケープ文字がありません。どの製品でも同じ意味にしたいときは、ESCAPEを明示して書きます。
大文字と小文字を区別するかは、製品と照合順序で決まる
LIKEが大文字と小文字を区別するかどうかは、製品によって違います。PostgreSQLのLIKEは既定の照合順序では区別するので、LIKE 'usb%' はUSBケーブルに一致しません。MySQLは、比べる文字列の照合順序で決まります。
| 製品 | 大文字と | 区別しないで探す方法 |
|---|---|---|
| PostgreSQL | 既定の | LIKEの |
| MySQL | 照合順序で | 名前が |
照合順序は、文字をどう比べて並べるかの決まりです。MySQLの文書は、照合順序の名前の_ciを大文字と小文字を区別しない印、_csを区別する印として説明しています。 _binは文字のコードの値で比べるので、大文字と小文字は別の文字になります。
MySQLの文書の例では、'abc' LIKE 'ABC' の結果は真です。PostgreSQLのILIKEは規格に無い独自の機能なので、ほかの製品ではそのまま使えないことがあります。
=・IN・BETWEENとLIKEの使い分け
値がぴったり分かっているなら、LIKEではなく=で比べます。候補の値がいくつか決まっているなら、INで並べます。LIKEを使うのは、値の一部だけが分かっているときです。
WHERE 商品名 = 'マウス' -- 完全一致
WHERE 商品名 IN ('マウス', 'マウスパッド') -- 候補のどれかと一致
WHERE 価格 BETWEEN 1000 AND 2000 -- 1000以上2000以下
WHERE 商品名 LIKE 'マウス%' -- マウスで始まるBETWEENは、値が範囲に入るかを調べる述語です。LIKEは文字の並びを調べるので、数値の大小は比べられません。
INとBETWEENをORやANDの式に書き換えた形と、BETWEENの両端の扱いは、INとBETWEENの記事で説明しています。INとEXISTSで別の表の値と比べる書き方は、サブクエリの記事にあります。
利用者が入力した語をそのままSQL文に埋め込むと、SQLインジェクションの原因になります。仕組みと対策は、SQLインジェクションとXSSの記事で説明しています。
前方一致はインデックスを使え、%で始まるパターンは使えない
インデックスに使うB-treeは、値を順に並べて持っています。LIKE 'USB%' のような前方一致なら、USBで始まる値が並ぶ範囲だけを索引でたどれます。%で始まるパターンは、どこから探せばよいかが決まらないので、索引の範囲をしぼれません。
MySQLの文書は、LIKEの右側が%や_で始まらない固定の文字列なら、インデックスを使えると説明しています。PostgreSQLの文書も、前方一致ならB-treeを使えると説明しています。ただしPostgreSQLでは、データベースのロケールがC以外だと、text_pattern_opsなどを指定したインデックスが必要です。
PostgreSQLで2万行の表にインデックスを作り、DBMSが選ぶ処理の手順(実行計画)を確かめました。LIKE 'item123%' では、索引で item123 以上 item124 未満の範囲を探す計画になりました。LIKE '%123' と LIKE '%m123%' では、全ての行を順に読む計画になりました。
参考にした資料
- PostgreSQL 18 文書「Pattern Matching」(%と_の意味、ESCAPE、ILIKE)
- PostgreSQL 18 文書「Index Types」(前方一致とB-tree)
- PostgreSQL 18 文書「Operator Classes and Operator Families」(text_pattern_ops)
- MySQL 8.4 Reference Manual「String Comparison Functions and Operators」(LIKEとNULL、既定のエスケープ文字、大文字と小文字)
- MySQL 8.4 Reference Manual「Collation Naming Conventions」
- MySQL 8.4 Reference Manual「Comparison of B-Tree and Hash Indexes」(LIKEでインデックスを使える条件)
練習問題(全5問)
正解:マウスA
_は
正解:ケーブルカバー
%ケーブルは、
正解:名前 LIKE '%!%%' ESCAPE '!'
ESCAPE '!' を
正解:一致しない
PostgreSQLの
正解:LIKE 'USB%'
先頭の
選んでから「採点する」を押すと、解説つきで答え合わせができます。
関連記事
おすすめの本 PR
セキュリティとデータベースは、基本情報技術者試験の対策本でまとめて学べます。

