MySQL 正規表現(Regexp)

⚡ スマートサマリー

MySQL 正規表現 (REGEXP) は、ワイルドカードでは表現できない柔軟なパターンに対して列の値を照合します。ここでは、REGEXP の構文、RLIKE の同義語、サポートされているすべてのメタ文字、myflixdb データベースに対する修正されたクエリ例、および追加された正規表現関数について説明します。 MySQL 8.0.

  • 🔍 ペース: Operaトール: REGEXPは列をパターンと比較し、一致した場合は1を返します。一方、RLIKEはREGEXPと全く同じ意味です。
  • 🧩 パターン Anchors: キャレット(^)は一致箇所を値の先頭に固定し、ドル記号($)は一致箇所を値の末尾に固定します。
  • 🔤 キャラクター一覧: [abcd] は囲まれた任意の文字に一致し、[^abcd] は結果セットから囲まれたすべての文字を除外します。
  • 数量指定子: アスタリスク、プラス記号、疑問符は、文字列全体ではなく、それらの直前の文字に適用されます。
  • 🛡️ エスカping ルール: パターン内では、文字通りのバックスラッシュは二重にする必要があります。 MySQL 文字列を2回処理する。
  • 🆕 バージョンの変更: MySQL 8.0 では ICU エンジンに移行し、[[:<:]] と [[:>:]] を \b に置き換え、REGEXP_LIKE、REGEXP_REPLACE、REGEXP_SUBSTR、REGEXP_INSTR を追加しました。
  • パフォーマンスに関する注意: 正規表現はインデックスを使用しないため、クエリで可能な場合は、まずインデックス付き条件で行をフィルタリングしてください。

何ですか MySQL 正規表現?

MySQL 正規表現 複雑な条件に一致するデータを検索するのに役立ちます。正規表現は、探している値そのものではなく、値の形状を記述するパターンです。

すでに一緒に仕事をしたことがあるなら MySQL ワイルドカードLIKE演算子でも同様の結果が得られるのに、なぜ正規表現を学ぶ価値があるのか​​疑問に思うかもしれません。その答えは表現力にあります。ワイルドカードは2つの記号しか使用できませんが、正規表現は文字範囲、代替文字、繰り返し、単語の位置などを単一のパターンで記述できます。

目的が明確になったところで、次のセクションでは、すべての正規表現クエリで使用する構文を紹介します。

正規表現の基本構文

正規表現の基本的な構文は以下のとおりです。

SELECT * FROM table_name
WHERE fieldname REGEXP 'pattern';

ここ:

  • 「SELECT文」 標準です SELECTステートメント.
  • 「WHERE フィールド名」 これは、正規表現が適用される列の名前です。
  • 「REGEXP 'パターン'」 — REGEXPは正規表現演算子であり、「pattern」は一致させるパターンを表します。 RLIKE   REGEXP の同義語 そして同じ結果を返します。LIKE演算子との混同を避けるため、REGEXPを使用することをお勧めします。

それでは、具体的な例を見てみましょう。

SELECT * FROM `movies`
WHERE `title` REGEXP 'code';

上記のクエリは、「code」という単語を含むすべての映画タイトルを検索します。「code」がタイトルの先頭、中間、末尾のいずれにあっても構いません。タイトルにこのパターンが含まれていれば、該当する行が返されます。

値の開始位置を文字リストと照合する

タイトルがa、b、c、またはdで始まり、その後に任意の数の文字が続く映画を探したいとします。そのためには、文字リストとキャレットメタ文字を組み合わせます。

SELECT * FROM `movies`
WHERE `title` REGEXP '^[abcd]';

上記のスクリプトを実行すると、 MySQL ワークベンチ myflixdbデータベースに対して以下の結果を得ました。

映画ID タイトル ディレクター リリース年 カテゴリ ID
4 Code 名前はブラック エドガー・ジムズ 2010 NULL
5 ダディーズ・リトル・ガールズ NULL 2007 8
6 天使と悪魔 NULL 2007 6
7 ダ・ヴィンチ Code NULL 2007 6

パターン「^[abcd]」では、キャレット(^)は値の先頭から一致を開始することを要求し、文字リスト[abcd]は最初の文字がa、b、c、またはdであるタイトルのみを受け入れます。デフォルトの照合順序では比較は大文字小文字を区別しないため、「Code 「名前 Black」が返されます。

否定文字リストを持つ文字を除外する

それでは、スクリプトを修正して文字リストを否定し、どの行が返されるかを確認してみましょう。

SELECT * FROM `movies`
WHERE `title` REGEXP '^[^abcd]';

上記のスクリプトを実行すると、 MySQL myflixdbデータベースに対してWorkbenchを実行すると、以下の結果が得られます。

映画ID タイトル ディレクター リリース年 カテゴリ ID
1 パイレーツ・オブ・カリビアン 4 ロブ·マーシャル 2011 1
2 サラ・マーシャルを忘れる ニコラス・ストーラー 2008 2
3 X-メン 2008
9 Honey moonERS ジョン・シュルツ 2005 8
16 67% 有罪 2012
17 チャップリンの独裁者 チャーリー・チャップリー 1920 7
18 サンプル動画 匿名の 8
19 映画3 ジョン·ブラウン 1920 8

文字リスト内では、キャレットの意味が変わります。「^[^abcd]」は引き続き一致箇所を先頭に固定しますが、「[^abcd]」は囲まれた文字のいずれかで始まるすべてのタイトルを除外します。

これら2つの例では、アンカーと文字リストのみを使用しています。次のセクションでは、メタ文字セット全体について説明します。

正規表現メタキャラクター

上記の例は、正規表現の最も単純な形式を示しています。メタ文字を使用すると、パターン検索を微調整できます。メタ文字は、繰り返し、代替、範囲、および位置を表します。以下の表は、サポートされているすべてのメタ文字を一覧にしたものです。 MySQL 正規表現演算子と、それぞれの修正例。

チャー 詳細説明 例:
* その アスタリスク(*) 0 個以上のインスタンスに一致する 一文字 それが先行します。 SELECT * FROM 映画 WHERE タイトル REGEXP 'da*'; 「d」の後に0個以上の「a」文字が続くパターンに一致するので、Da Vinci Code 「Daddy's Little Girls」も該当します。「a」の文字が必ず含まれている場合は、「da+」を使用してください。
+ その プラス(+) 直前の文字が1回以上出現するのと一致する。 SELECT * FROM `映画` WHERE `タイトル` REGEXP 'mon+'; 「mon」の後に「n」の文字が1つ以上続く映画をすべて表示します。例えば、「天使と悪魔」などです。
? その 疑問符(?) 直前の文字と0回または1回一致する。 SELECT * FROM `カテゴリ` WHERE `カテゴリ名` REGEXP 'com?'; 「co」にオプションで「m」を付けて一致させます。例:comedy(コメディ)とromantic comedy(ロマンティック・コメディ)。
. その ドット(.) 改行文字を除く任意の1文字に一致します。 SELECT * FROM 映画 WHERE `公開年` REGEXP '200.'; 「200」の後に任意の数字が続く年に公開されたすべての映画を表示します。例:2005、2007、2008。
[ABC] その 文字一覧 [abc] 囲まれた文字のいずれか1つに一致します。 SELECT * FROM `映画` WHERE `タイトル` REGEXP '[vwxyz]'; 「vwxyz」に含まれる任意のキャラクターが1人でも含まれている映画をすべて表示します。例えば、X-メンとダ・ヴィンチ Code.
[^ abc] その 否定リスト [^abc] 囲まれた文字以外の任意の文字に一致します。 SELECT * FROM `映画` WHERE `タイトル` REGEXP '^[^vwxyz]'; タイトルが「vwxyz」の文字で始まらないすべての映画を返します。
[AZ] その 範囲 [AZ] 任意の大文字に一致します。 SELECT * FROM `members` WHERE `postal_address` REGEXP '[AZ]'; 住所にAからZまでの文字が含まれるすべての会員に通知します。例えば、会員番号1のジャネット・ジョーンズなどです。
[az] その 範囲 [方位角] 任意の小文字に一致します。 SELECT * FROM `members` WHERE `postal_address` REGEXP '[az]'; 住所に「a」から「z」までの文字が含まれるすべての会員を表示します。デフォルトの照合順序は大文字と小文字を区別しないため、この範囲は大文字にも一致することに注意してください。
[0-9] その 範囲[0-9] 0から9までの任意の数字に一致します。 SELECT * FROM `members` WHERE `contact_number` REGEXP '[0-9]'; 連絡先番号に少なくとも1桁の数字が含まれているすべてのメンバーを表示します。たとえば、Robert Phil。
^ その キャレット (^) マッチを値の開始点に固定します。 SELECT * FROM `映画` WHERE `タイトル` REGEXP '^[cd]'; タイトルが「c」または「d」で始まるすべての映画を表示します。たとえば、 Code 名前ブラック、パパの小さな女の子たち、そしてダ・ヴィンチ Code.
$ その ドル記号 ($) 値の末尾にマッチを固定します。 SELECT * FROM `movies` WHERE `title` REGEXP 'code$'; タイトルが「code」で終わるすべての映画を表示します。たとえば、ダヴィンチ Code.
| その 縦棒 (|) 代替案を分離する。 SELECT * FROM `映画` WHERE `タイトル` REGEXP '^[cd]|^[u]'; タイトルが「c」、「d」、または「u」で始まるすべての映画を表示します。たとえば、 Code 名前 ブラック、ダ・ヴィンチ Code、そしてアンダーワールド – Awakenる。
\b その 単語境界(\b) 単語の先頭または末尾に一致します。これは、古い [[:<:]] および [[:>:]] マーカーに取って代わります。 MySQL 8.0は削除されました。 SELECT * FROM `movies` WHERE `title` REGEXP '\\bfor'; 「for」で始まる単語を含むすべての映画を表示します。たとえば、「Forgetting Sarah Marshal」などです。 MySQL 5.7 同等のパターンは '[[:<:]]for' です。
[[:クラス:]] その キャラクタークラス 指定された文字グループに一致します: [[:alpha:]] は文字、[[:space:]] は空白、[[:punct:]] は句読点、[[:upper:]] は大文字です。 角括弧。 SELECT * FROM `movies` WHERE `title` REGEXP '^[[:alpha:][:space:]]+$'; タイトルに文字とスペースのみが含まれる映画をすべて表示します。たとえば、「Forgetting Sarah Marshal」は表示されますが、「Pirates of the Caribean 4」は数字が含まれているため除外されます。

バックスラッシュ(\)はエスケープ文字です。 MySQL 文字列を最初に解析し、次にパターンを解析します。リテラルのバックスラッシュは、REGEXP パターン内では二重バックスラッシュ (\\) として記述する必要があります。

⚠️ バージョン警告: MySQL 8.0.4 では、古い正規表現エンジンが ICU ライブラリに置き換えられました。このリリースでは単語マーカー [[:<:]] と [[:>:]] が削除されたため、古い資料からコピーされたパターンは「構文エラー」で失敗します。 MySQL 8.0. 代わりに \b を使用してください。

すべてのメタ文字が定義された今、当然の疑問が生じます。より単純なLIKE演算子をREGEXPに置き換えるべきなのはどのような場合でしょうか?

REGEXPとLIKE:どちらを使うべきか?

どちらの演算子もパターンに基づいて行をフィルタリングしますが、解決する問題は異なります。LIKEは2つの記号しか認識しませんが、REGEXPは上記に示したメタ文字セット全体を認識します。この強力な機能には代償が伴うため、どちらを選ぶかは好みの問題ではなく、トレードオフの問題です。

基準 LIKE REGEXP
パターン記号 % と _ のみ Anchors、範囲、交替、量指定子、文字クラス
典型的な使用 接頭辞、接尾辞、および「含む」検索 検証、複数の選択肢、位置認識マッチング
インデックスの使用状況 パターンが%で始まらない場合に可能 インデックスを一切使用しない
戻り値 正しいか間違っているか 1または0、あるいはどちらかのオペランドがNULLの場合はNULL

単純なマッチングには、読みやすくインデックスも使用できるLIKEを使用してください。単一のパターンで複数のルールを同時に表現する必要がある場合(例:「cまたはdで始まり、数字で終わる」)は、REGEXPを使用してください。大きなテーブルの場合は、まずインデックス条件を使用して行を絞り込み、その絞り込まれたセットにREGEXPを適用してください。

MySQL 8.0 正規表現関数

REGEXP演算子は、値がパターンに一致するかどうかという1つの質問にのみ答えます。 MySQL 8.0ではさらに進んで、例えば、tract と一致するテキストを書き換えます。それぞれオプションの match_type 引数を受け付け、'c' は大文字小文字を区別する比較を強制し、'i' は大文字小文字を区別しない比較を強制します。

  • REGEXP_LIKE(expr, pattern) 値がパターンに一致する場合に 1 を返します。これは REGEXP 演算子の関数形式であり、match_type 引数によって大文字と小文字の区別が明示されます。
  • REGEXP_INSTR(expr, pattern) 一致した最初の文字の位置を返します。パターンが見つからない場合は 0 を返します。
  • REGEXP_SUBSTR(expr, pattern) 一致する部分文字列自体を返します。これは、長いテキスト値から年、コード、または数値を抽出する場合に便利です。
  • REGEXP_REPLACE(expr, pattern, replacement) 一致するすべての値を置き換えて返します。これにより、内部のデータをクリーンアップできます。 SQL UPDATEクエリ.
SELECT title,
       REGEXP_SUBSTR(title, '[0-9]+') AS number_in_title
FROM `movies`
WHERE REGEXP_LIKE(title, '[0-9]');

上記のクエリは、数字を含むすべての映画タイトルと、その数字自体を返します。 MySQL 5.7 これらの関数は利用できないため、REGEXP 演算子が唯一の選択肢となります。

よくあるご質問

デフォルトではそうではありません。REGEXP は列の照合順序に従いますが、標準の照合順序では大文字と小文字は区別されません。大文字と小文字を区別する比較を強制するには、列の前に BINARY キーワードを追加するか、REGEXP_LIKE 関数を「c」マッチタイプで呼び出してください。

機能的な違いはありません。RLIKEはREGEXPの同義語です。 MySQL 互換性のために保持します。実際には、RLIKE は無関係な文字列と混同されやすいため、REGEXP が推奨されます。 LIKE演算子 ワイルドカードに使用されます。

正規表現ではインデックスを使用できないため MySQL パターンを1行ずつ評価します。まず、インデックス条件、日付範囲、または全文検索インデックスを使用してスキャン対象の行数を絞り込み、その絞り込まれた結果セットに正規表現を適用します。

はい。AIアシスタントは平易な言葉のルールを正規表現パターンに変換し、各メタ文字を説明します。結果をテストするには MySQL ワークベンチ サンプル行と比較すると、アンカーの位置が1つずれるだけで結果セット全体が変わってしまうため、注意が必要です。

はい。AIアシスタントは、句読点の削除、電話番号の正規化、不要なスペースの削除を行うREGEXP_REPLACEステートメントを生成します。まずSELECT内でパターンを実行し、書き換えられた値を確認してから、それを適用してください。 UPDATE ステートメント.