PostgreSQL正規表現の使い方|検索・抽出・置換を実務解説
CONTENTS
- 1 PostgreSQLで正規表現を使う主な場面
- 2 PostgreSQLで使える正規表現演算子
- 3 WHERE句で正規表現検索を行う基本
- 4 LIKE・SIMILAR TO・正規表現の違い
- 5 regexp_matchとregexp_matchesで文字列を抽出する
- 6 regexp_replaceで文字列を置換・正規化する
- 7 regexp_split_to_tableとregexp_split_to_arrayで文字列を分割する
- 8 実務でよく使うPostgreSQL正規表現パターン集
- 9 PostgreSQL正規表現で注意すべきエスケープ
- 10 NULLを含むデータに正規表現を使うときの注意点
- 11 正規表現検索のパフォーマンスとインデックス設計
- 12 PostgreSQL正規表現のよくある失敗
- 13 PostgreSQL正規表現を実務で安全に使うためのチェックリスト
- 14 PostgreSQL正規表現の学習に役立つ公式情報・参考情報
- 15 まとめ:PostgreSQLの正規表現は「検索」だけでなくデータ品質改善にも役立つ
PostgreSQLで文字列検索やログ解析、データクレンジングを行っていると、「LIKEでは条件を書ききれない」「メールアドレスや電話番号の形式をまとめて確認したい」「文字列の一部だけを抽出したい」と感じる場面があります。
そのようなときに役立つのが、PostgreSQLの正規表現です。
正規表現を使うと、単なる部分一致だけでなく、次のような処理をSQL上で実現できます。
- 特定の形式に一致するデータを検索する
- 大文字・小文字を無視して検索する
- 不正な形式のデータを抽出する
- 文字列から必要な部分だけを取り出す
- ハイフンや空白を除去してデータを正規化する
- ログやテキストを区切り文字で分割する
PostgreSQLでは、~ や ~* などの正規表現演算子に加えて、regexp_match、regexp_matches、regexp_replace、regexp_split_to_table などの関数が用意されています。公式ドキュメントでも、POSIX正規表現によるパターンマッチ、抽出、置換、分割の機能が整理されています。参考情報としては、PostgreSQL公式ドキュメントの「Pattern Matching」が最も信頼できます。
https://www.postgresql.org/docs/current/functions-matching.html
この記事では、PostgreSQLの正規表現について、基本の演算子から実務でよく使う関数、パターン例、エスケープやNULL、パフォーマンス上の注意点までを体系的に解説します。
PostgreSQLで正規表現を使う主な場面
PostgreSQLの正規表現は、単に「文字列を検索するための便利機能」ではありません。実務では、データ品質の確認、移行データの検証、ログ分析、入力値チェック、レポート前のデータ整形など、幅広い場面で使われます。
LIKEでは表現しづらい検索条件を書きたいとき
LIKE はシンプルな部分一致や前方一致に向いています。
SELECT *
FROM users
WHERE name LIKE 'A%';
このように「Aで始まる名前」を探す程度であれば、LIKE で十分です。
しかし、次のような条件になると、LIKE だけでは表現が難しくなります。
- 数字4桁だけのコードを探したい
- 英字と数字だけで構成されたIDを探したい
- メールアドレスらしい形式の値を探したい
- 電話番号に数字とハイフン以外が含まれていないか確認したい
- ログ本文から特定パターンのIDだけを抽出したい
このような場合は、正規表現を使うことで条件を簡潔に書けます。
SELECT *
FROM users
WHERE user_code ~ '^[0-9]{4}$';
このSQLは、user_code が「数字4桁だけ」で構成されている行を検索します。
データクレンジングや移行データの検証をしたいとき
実務では、きれいなデータだけを扱えるとは限りません。
たとえば、電話番号カラムに次のような値が混在していることがあります。
03-1234-5678
0312345678
03 1234 5678
TEL:03-1234-5678
不明
このようなデータに対して、「数字以外を除去する」「電話番号として扱えない値を抽出する」といった処理を行う場合、正規表現が有効です。
SELECT regexp_replace(phone, '[^0-9]', '', 'g') AS normalized_phone
FROM users;
regexp_replace を使うと、数字以外の文字をまとめて削除できます。
ログやテキストから必要な情報を抽出したいとき
アプリケーションログやアクセスログには、ユーザーID、IPアドレス、リクエストURL、エラーコードなどが文字列として含まれていることがあります。
たとえば、次のようなログがあるとします。
ERROR user_id=12345 status=500 path=/api/orders
ここから user_id の数字部分だけを取り出したい場合、regexp_match を使えます。
SELECT (regexp_match(log_text, 'user_id=([0-9]+)'))[1] AS user_id
FROM app_logs;
このように、PostgreSQLの正規表現は、検索だけでなく「文字列から意味のある情報を取り出す」用途でも活躍します。
PostgreSQLで使える正規表現演算子
PostgreSQLで正規表現検索を行う基本は、~、~*、!~、!~* の4つの演算子です。
公式ドキュメントでも、POSIX正規表現のマッチ演算子としてこれらの演算子が整理されています。~ は大文字・小文字を区別する一致、~* は大文字・小文字を区別しない一致、!~ と !~* はそれぞれ不一致を判定します。
正規表現演算子の一覧
| 演算子 | 意味 | 大文字・小文字 |
|---|---|---|
~ |
正規表現に一致する | 区別する |
~* |
正規表現に一致する | 区別しない |
!~ |
正規表現に一致しない | 区別する |
!~* |
正規表現に一致しない | 区別しない |
たとえば、title カラムに PostgreSQL という文字列が含まれる行を検索する場合は、次のように書きます。
SELECT *
FROM articles
WHERE title ~ 'PostgreSQL';
大文字・小文字を区別せずに検索したい場合は、~* を使います。
SELECT *
FROM articles
WHERE title ~* 'postgresql';
この場合、PostgreSQL、POSTGRESQL、postgresql などの表記ゆれをまとめて検索できます。
PostgreSQLの正規表現は部分一致が基本
PostgreSQLの正規表現を使うときに、最初に理解しておきたい重要なポイントがあります。
それは、アンカーを指定しない限り、文字列のどこかに一致すれば真になるという点です。
SELECT 'abcd' ~ 'bc';
この結果は true になります。
つまり、bc が文字列全体と一致していなくても、途中に含まれていれば一致と判定されます。公式ドキュメントでも、正規表現は明示的に先頭・末尾へ固定しない限り、文字列内の任意の場所に一致できると説明されています。
そのため、完全一致を期待している場合は、必ず ^ と $ を使って条件を明確にする必要があります。
SELECT *
FROM users
WHERE code ~ '^[0-9]{4}$';
このSQLは「数字4桁を含む」ではなく、「数字4桁だけで構成されている」値を検索します。
WHERE句で正規表現検索を行う基本
PostgreSQLの正規表現は、WHERE句で行を絞り込む用途が最もよく使われます。
特定の文字列を含む行を検索する
SELECT *
FROM logs
WHERE message ~ 'ERROR';
このSQLは、message カラムに ERROR を含む行を検索します。
大文字・小文字を区別しない場合は、次のようにします。
SELECT *
FROM logs
WHERE message ~* 'error';
ログでは ERROR、Error、error など表記が揺れることがあるため、実務では ~* が便利です。
先頭一致を検索する
文字列の先頭に一致させたい場合は、^ を使います。
SELECT *
FROM users
WHERE user_id ~ '^A';
このSQLは、user_id が A で始まるユーザーを検索します。
末尾一致を検索する
文字列の末尾に一致させたい場合は、$ を使います。
SELECT *
FROM files
WHERE file_name ~ '\.csv$';
このSQLは、.csv で終わるファイル名を検索します。
. は正規表現では「任意の1文字」を意味する特殊文字です。そのため、通常のドットとして扱いたい場合は \. のようにエスケープします。
完全一致を検索する
完全一致を表現するには、^ と $ を両方使います。
SELECT *
FROM products
WHERE product_code ~ '^[A-Z]{3}[0-9]{4}$';
このSQLは、次のような形式に一致します。
ABC1234
XYZ9999
一方で、次のような値は一致しません。
AB1234
ABC12345
xABC1234
ABC1234x
実務では、コード、社員番号、商品番号、郵便番号などの形式チェックでよく使います。
LIKE・SIMILAR TO・正規表現の違い
PostgreSQLには、文字列パターンを扱う方法が複数あります。代表的なものが、LIKE、SIMILAR TO、POSIX正規表現です。
公式ドキュメントでも、PostgreSQLのパターンマッチには LIKE、SIMILAR TO、POSIX正規表現の3種類があると説明されています。
LIKEは単純な検索に向いている
LIKE は、最もシンプルで読みやすいパターンマッチです。
SELECT *
FROM articles
WHERE title LIKE '%PostgreSQL%';
LIKE で使える主な記号は次の2つです。
| 記号 | 意味 |
|---|---|
% |
0文字以上の任意の文字列 |
_ |
任意の1文字 |
単純な前方一致、後方一致、部分一致であれば、正規表現よりも LIKE の方が読みやすく、チーム開発でもレビューしやすいです。
SIMILAR TOはSQL標準寄りのパターンマッチ
SIMILAR TO は、SQL標準に近い正規表現風のパターンマッチです。
ただし、実務では LIKE か POSIX正規表現のどちらかを使うケースが多く、SIMILAR TO はやや中間的な存在です。
注意点として、SIMILAR TO は文字列全体がパターンに一致するかを判定します。部分一致にしたい場合は、% を組み合わせる必要があります。
SELECT 'abc' SIMILAR TO '%b%';
実務ではLIKEと正規表現を使い分ける
使い分けの目安は次の通りです。
| 用途 | 推奨 |
|---|---|
| 単純な部分一致 | LIKE |
| 大文字・小文字を無視した単純検索 | ILIKE または ~* |
| 形式チェック | 正規表現 |
| 複雑な抽出 | regexp_match / regexp_matches |
| 文字列の正規化 | regexp_replace |
| テキスト分割 | regexp_split_to_table / regexp_split_to_array |
正規表現は強力ですが、複雑にしすぎると可読性と保守性が下がります。まずは LIKE で足りるかを考え、要件が複雑な場合に正規表現を使うのが実務的です。
regexp_matchとregexp_matchesで文字列を抽出する
正規表現演算子は「一致するかどうか」を判定するのに向いています。一方で、文字列から必要な部分を取り出したい場合は、regexp_match や regexp_matches を使います。
公式ドキュメントでは、regexp_match は最初に一致した部分文字列を text 配列で返し、regexp_matches は一致結果を行集合として返す関数として説明されています。regexp_matches は g フラグを付けることで複数の一致を返せます。
regexp_matchは最初の1件を抽出する
regexp_match は、最初に一致した結果を配列で返します。
SELECT regexp_match('user_id=12345', 'user_id=([0-9]+)');
結果は次のようになります。
{12345}
配列の1番目の要素を取り出す場合は、次のように書きます。
SELECT (regexp_match('user_id=12345', 'user_id=([0-9]+)'))[1] AS user_id;
実務では、ログ本文やメッセージ本文からID、コード、日付、URLなどを抽出する場面で使います。
キャプチャグループを使って必要な部分だけ取り出す
正規表現の () は、キャプチャグループです。
SELECT (regexp_match('order_id=ORD-2026-001', 'order_id=(ORD-[0-9]{4}-[0-9]{3})'))[1] AS order_id;
このSQLでは、order_id= の後ろに続く注文IDだけを抽出します。
ポイントは、検索に使いたい文字列と、実際に取り出したい文字列を分けられることです。
regexp_matchesは複数の一致を抽出する
1つの文字列内に同じパターンが複数回出てくる場合は、regexp_matches を使います。
SELECT regexp_matches(
'url=/users/1 url=/orders/10 url=/items/3',
'url=([^ ]+)',
'g'
);
g フラグを付けることで、すべての一致を取得できます。
ログ解析やテキスト分析では、1行の中に複数のURLやIDが含まれることがあるため、regexp_matches が有効です。
regexp_matchとregexp_matchesの使い分け
| 関数 | 向いている用途 |
|---|---|
regexp_match |
最初の1件だけ取り出す |
regexp_matches |
複数の一致をすべて取り出す |
基本的には、最初の1件だけでよいなら regexp_match、複数抽出が必要なら regexp_matches と覚えておけば問題ありません。
ただし、regexp_matches は一致しない場合に行を返さないため、SELECT句やJOINで使う場合は注意が必要です。元の行を残したい場合は、LEFT JOIN LATERAL などを検討します。
regexp_replaceで文字列を置換・正規化する
regexp_replace は、正規表現に一致した文字列を別の文字列へ置換する関数です。
公式ドキュメントでは、regexp_replace はPOSIX正規表現パターンに一致した部分文字列を置換する関数として説明されており、デフォルトでは最初の一致だけが置換され、g フラグを指定するとすべての一致を置換できます。
基本的な置換
SELECT regexp_replace('abc123def', '[0-9]+', 'XXX');
結果は次のようになります。
abcXXXdef
数字部分を XXX に置換しています。
すべて置換する場合はgフラグを使う
regexp_replace は、フラグを省略すると最初の1件だけを置換します。
SELECT regexp_replace('abc123def456', '[0-9]+', 'XXX');
結果は次のようになります。
abcXXXdef456
すべての数字部分を置換したい場合は、g フラグを指定します。
SELECT regexp_replace('abc123def456', '[0-9]+', 'XXX', 'g');
結果は次のようになります。
abcXXXdefXXX
この g フラグを忘れると、想定したクレンジングにならないことがあります。実務では必ずサンプルデータで結果を確認してから本番データに適用しましょう。
数字以外を削除して電話番号を正規化する
電話番号や金額のように、余計な記号が混ざりやすいデータでは、regexp_replace が便利です。
SELECT regexp_replace('03-1234-5678', '[^0-9]', '', 'g') AS phone;
結果は次のようになります。
0312345678
[^0-9] は「数字以外」を意味します。
同じ考え方で、金額からカンマや円記号を削除することもできます。
SELECT regexp_replace('1,234円', '[^0-9]', '', 'g') AS price;
結果は次のようになります。
1234
ただし、電話番号の先頭ゼロや、小数点、マイナス記号を保持したい場合は注意が必要です。何を削除し、何を残すべきかは、業務要件に合わせて設計する必要があります。
後方参照を使って文字列を並び替える
regexp_replace では、キャプチャした文字列を置換後の文字列で再利用できます。
SELECT regexp_replace('2026-05-19', '([0-9]{4})-([0-9]{2})-([0-9]{2})', '\1年\2月\3日');
結果は次のようになります。
2026年05月19日
\1、\2、\3 は、それぞれ1番目、2番目、3番目のキャプチャグループを表します。
日付やコードの表示形式を変換したいときに便利です。
regexp_split_to_tableとregexp_split_to_arrayで文字列を分割する
文字列を区切り文字で分割したい場合は、regexp_split_to_table または regexp_split_to_array を使います。
公式ドキュメントでは、regexp_split_to_table は正規表現パターンを区切りとして文字列を行に分割し、regexp_split_to_array は同じ結果を配列として返す関数として説明されています。
regexp_split_to_tableで行に分割する
SELECT word
FROM regexp_split_to_table('PostgreSQL regex SQL', '\s+') AS word;
結果は次のようになります。
PostgreSQL
regex
SQL
\s+ は、1つ以上の空白文字を意味します。
タグ、キーワード、ログ内のトークンなどを1行ずつ扱いたい場合に便利です。
regexp_split_to_arrayで配列に分割する
配列として受け取りたい場合は、regexp_split_to_array を使います。
SELECT *
FROM users
WHERE employee_no ~ '^[0-9]+$';
結果は次のようになります。
{PostgreSQL,MySQL,SQLite}
後続処理で unnest したい場合や、配列関数と組み合わせたい場合に向いています。
分割条件は空文字にマッチしないようにする
分割で注意したいのは、区切りパターンが空文字にマッチしてしまうケースです。
たとえば、\s* のように「空白0文字以上」を区切りにすると、意図しない細かい分割になることがあります。
基本的には、空白区切りなら \s+、カンマ区切りなら \s*,\s* のように、「実際に区切りとして存在する文字」に一致するパターンを使いましょう。
実務でよく使うPostgreSQL正規表現パターン集
ここでは、実務でよく使う正規表現パターンを紹介します。
ただし、正規表現による入力チェックは、厳密にしすぎると保守が難しくなります。特にメールアドレスや電話番号は、仕様や表記ゆれが多いため、「明らかな不正を除外するための簡易チェック」として使うのが現実的です。
半角英数字のみをチェックする
SELECT *
FROM users
WHERE login_id ~ '^[A-Za-z0-9]+$';
このSQLは、login_id が半角英数字のみで構成されている行を検索します。
空文字を許可する場合は、+ ではなく * を使います。
'^[A-Za-z0-9]*$'
アンダースコアも許可する場合は、次のようにします。
'^[A-Za-z0-9_]+$'
数字のみをチェックする
SELECT *
FROM users
WHERE employee_no ~ '^[0-9]+$';
社員番号、会員番号、管理番号などが数字のみか確認するときに使えます。
桁数まで指定したい場合は、次のようにします。
SELECT *
FROM users
WHERE employee_no ~ '^[0-9]{6}$';
このSQLは、6桁の数字だけを許可します。
郵便番号をチェックする
ハイフンありの郵便番号をチェックする場合は、次のように書けます。
SELECT *
FROM addresses
WHERE postal_code ~ '^[0-9]{3}-[0-9]{4}$';
ハイフンなしも許可する場合は、次のようにできます。
SELECT *
FROM addresses
WHERE postal_code ~ '^[0-9]{3}-?[0-9]{4}$';
-? は「ハイフンが0回または1回」を意味します。
メールアドレスの簡易チェック
SELECT *
FROM users
WHERE email ~* '^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$';
~* を使うことで、大文字・小文字を区別せずにチェックできます。
ただし、メールアドレスの仕様を正規表現だけで完全に判定するのは現実的ではありません。実務では、形式の簡易チェック、確認メール送信、ドメイン制御などを組み合わせる方が安全です。
電話番号の簡易チェック
SELECT *
FROM users
WHERE phone ~ '^[0-9-]+$';
これは、数字とハイフンだけで構成されているかを確認する簡易チェックです。
不正なデータを探す場合は、否定条件を使います。
SELECT *
FROM users
WHERE phone IS NULL
OR phone !~ '^[0-9-]+$';
ここで phone IS NULL を含めている点が重要です。!~ だけでは、NULLの値は抽出されません。
PostgreSQL正規表現で注意すべきエスケープ
PostgreSQLで正規表現を使うときに、初心者がつまずきやすいのがエスケープです。
正規表現には、.、*、+、?、^、$、[、]、(、)、| などの特殊文字があります。
これらを通常の文字として扱いたい場合は、バックスラッシュでエスケープします。
ドットを通常の文字として扱う
ファイル名が .csv で終わるか確認したい場合、次のように書きます。
SELECT *
FROM files
WHERE file_name ~ '\.csv$';
. をエスケープしないと、「任意の1文字」という意味になってしまいます。
SQL文字列と正規表現のエスケープが重なる
PostgreSQLでは、SQL文字列としてのエスケープと、正規表現としてのエスケープが重なる場合があります。
特に、バックスラッシュや後方参照を扱う場合は、想定通りの文字列として解釈されているかを確認することが重要です。
複雑な正規表現を本番SQLに直接書く前に、次のような小さなSELECT文で動作確認する習慣を付けると安全です。
SELECT regexp_replace('03-1234-5678', '[^0-9]', '', 'g');
正規表現は1文字の違いで結果が大きく変わるため、実務では「本番更新前にSELECTで確認する」ことが非常に重要です。
NULLを含むデータに正規表現を使うときの注意点
PostgreSQLの正規表現で見落としやすいのが、NULLの扱いです。
たとえば、次のSQLを考えます。
SELECT *
FROM users
WHERE phone !~ '^[0-9-]+$';
このSQLは、「数字とハイフン以外を含む電話番号」を探す条件です。
しかし、phone が NULL の行は、この条件では抽出されません。
SQLでは、NULLは「値がない」状態であり、一致でも不一致でもありません。そのため、監査やデータ品質チェックでNULLも不正として扱いたい場合は、明示的に条件へ含める必要があります。
SELECT *
FROM users
WHERE phone IS NULL
OR phone !~ '^[0-9-]+$';
実務では、「NULLを許容するのか」「空文字を許容するのか」「不正データとして扱うのか」を最初に決めてから、正規表現条件を書くことが重要です。
正規表現検索のパフォーマンスとインデックス設計
PostgreSQLの正規表現は便利ですが、検索対象のデータ量が多い場合はパフォーマンスに注意が必要です。
正規表現は全表走査になりやすい
次のようなSQLは、データ量が多いテーブルでは重くなる可能性があります。
SELECT *
FROM logs
WHERE message ~ 'error_code=[0-9]+';
正規表現検索は、通常のB-treeインデックスが効きにくいケースがあります。特に、文字列の途中に一致するパターンや、複雑な繰り返しを含むパターンでは、全表走査になりやすくなります。
まず前段条件で対象を絞る
実務では、いきなり正規表現を全件に適用するのではなく、日付や種別などで対象を絞ってから正規表現を使うのが基本です。
SELECT *
FROM logs
WHERE created_at >= CURRENT_DATE - INTERVAL '7 days'
AND level = 'ERROR'
AND message ~ 'user_id=[0-9]+';
このように、先にインデックスが効きやすい条件で件数を減らすことで、正規表現処理の負荷を抑えられます。
pg_trgmを使った高速化も検討する
大量のテキスト検索や部分一致検索を扱う場合は、pg_trgm 拡張の利用も検討できます。
PostgreSQL公式ドキュメントでは、pg_trgm は文字列の類似度判定や高速な類似検索を支援するモジュールであり、GiSTやGINインデックスを使って LIKE、ILIKE、~、~* などの検索を支援できると説明されています。
https://www.postgresql.org/docs/current/pgtrgm.html
例として、次のようにGINインデックスを作成できます。
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX idx_logs_message_trgm
ON logs
USING GIN (message gin_trgm_ops);
ただし、pg_trgm を使えばすべての正規表現が高速になるわけではありません。パターンから有効なトライグラムを抽出できない場合は、期待した効果が出ないこともあります。
そのため、実務では必ず EXPLAIN ANALYZE で実行計画と実行時間を確認しましょう。
EXPLAIN ANALYZE
SELECT *
FROM logs
WHERE message ~ 'error_code=[0-9]+';
PostgreSQL正規表現のよくある失敗
PostgreSQLの正規表現は強力ですが、実務ではいくつかの失敗がよく起こります。
アンカーを付け忘れて想定外の値が一致する
たとえば、数字4桁のコードを検索したい場合、次のSQLでは不十分です。
SELECT *
FROM users
WHERE code ~ '[0-9]{4}';
この条件では、ABC1234XYZ のように数字4桁を含む値も一致します。
完全に数字4桁だけを許可したいなら、次のように書きます。
SELECT *
FROM users
WHERE code ~ '^[0-9]{4}$';
regexp_replaceでgフラグを忘れる
すべての数字を削除したい場合、次のSQLでは最初の一致しか置換されません。
SELECT regexp_replace('abc123def456', '[0-9]+', '');
すべて置換するには、g フラグが必要です。
SELECT regexp_replace('abc123def456', '[0-9]+', '', 'g');
NULLを不正データとして拾えていない
不正な電話番号を探すSQLとして、次の条件だけを書くとNULLが漏れます。
WHERE phone !~ '^[0-9-]+$'
NULLも対象にするなら、次のようにします。
WHERE phone IS NULL
OR phone !~ '^[0-9-]+$'
複雑すぎる正規表現で保守できなくなる
正規表現は、条件を詰め込みすぎると読みにくくなります。
たとえば、メールアドレス、電話番号、住所、コード体系などをすべて1つの正規表現で厳密に判定しようとすると、後から誰も修正できないSQLになりがちです。
実務では、次のように分けて考えることが重要です。
- DBでは最低限の形式チェックを行う
- アプリケーション側で詳細なバリデーションを行う
- 保存前に正規化する
- 表示時にフォーマットを整える
- 例外データは別途監査・補正する
正規表現だけですべてを解決しようとしないことが、保守性の高い設計につながります。
PostgreSQL正規表現を実務で安全に使うためのチェックリスト
PostgreSQLで正規表現を使うときは、次の観点を確認しておくと安全です。
検索条件の意図が明確か
まず、「部分一致」なのか「完全一致」なのかを明確にします。
完全一致であれば、^ と $ を使います。
'^[0-9]{4}$'
部分一致でよければ、アンカーなしで問題ありません。
'[0-9]{4}'
この違いを曖昧にしたままSQLを書くと、想定外のデータが検索対象になります。
LIKEで十分ではないか
正規表現を使う前に、LIKE で十分かを確認しましょう。
WHERE title LIKE '%PostgreSQL%'
この程度の条件であれば、正規表現よりも LIKE の方が読みやすいです。
正規表現を使うべきなのは、文字種、桁数、繰り返し、抽出、置換などが必要な場合です。
NULLや空文字の扱いを決めているか
NULLと空文字は別物です。
phone IS NULL
phone = ''
監査条件では、NULL、空文字、不正形式をそれぞれどう扱うかを明確にしましょう。
本番更新前にSELECTで確認しているか
UPDATE と regexp_replace を組み合わせる場合、いきなり更新するのは危険です。
まずはSELECTで変換結果を確認します。
SELECT
phone,
regexp_replace(phone, '[^0-9]', '', 'g') AS normalized_phone
FROM users;
問題がないことを確認してから、UPDATEを実行します。
UPDATE users
SET phone = regexp_replace(phone, '[^0-9]', '', 'g');
実行計画を確認しているか
大量データに対して正規表現検索を行う場合は、EXPLAIN ANALYZE で実行計画を確認しましょう。
EXPLAIN ANALYZE
SELECT *
FROM logs
WHERE message ~ 'error_code=[0-9]+';
処理が重い場合は、次の対策を検討します。
- 日付やステータスで先に対象を絞る
- 正規化済みの別カラムを用意する
- 検索用カラムを追加する
pg_trgmのGIN/GiSTインデックスを検討する- アプリケーション側で処理する範囲を見直す
PostgreSQL正規表現の学習に役立つ公式情報・参考情報
PostgreSQLの正規表現を正確に理解するには、公式ドキュメントを確認するのが最も確実です。
PostgreSQL公式ドキュメント:Pattern Matching
PostgreSQLの LIKE、SIMILAR TO、POSIX正規表現、regexp_match、regexp_matches、regexp_replace、regexp_split_to_table などを確認できます。
https://www.postgresql.org/docs/current/functions-matching.html
PostgreSQL公式ドキュメント:pg_trgm
LIKE、ILIKE、正規表現検索、類似検索を高速化したい場合に参考になります。
https://www.postgresql.org/docs/current/pgtrgm.html
日本PostgreSQLユーザ会
日本語でPostgreSQL関連情報を確認したい場合は、日本PostgreSQLユーザ会も参考になります。日本語訳マニュアルやイベント情報、コミュニティ情報が掲載されています。
https://www.postgresql.jp/
まとめ:PostgreSQLの正規表現は「検索」だけでなくデータ品質改善にも役立つ
PostgreSQLの正規表現は、LIKE では表現しづらい複雑な文字列検索を行うための強力な機能です。
特に、次のポイントを押さえておくと、実務で安全に使いやすくなります。
~は大文字・小文字を区別する正規表現一致~*は大文字・小文字を区別しない正規表現一致!~、!~*は不一致の判定に使う- アンカーなしの正規表現は部分一致になりやすい
- 完全一致には
^と$を使う - 抽出には
regexp_match、複数抽出にはregexp_matchesを使う - 置換・正規化には
regexp_replaceを使う - 分割には
regexp_split_to_tableやregexp_split_to_arrayを使う - NULLは正規表現の不一致条件だけでは拾えない
- 大量データではパフォーマンスとインデックス設計に注意する
- 必要に応じて
pg_trgmの利用も検討する
正規表現は便利な一方で、複雑に書きすぎると保守性を下げる原因にもなります。まずは LIKE で足りるかを判断し、形式チェック、抽出、置換、分割など、正規表現の強みが必要な場面で使うのが実務的です。
PostgreSQLの正規表現を理解できると、単なるSQL検索だけでなく、ログ解析、データクレンジング、移行データの検証、入力値チェックなど、より実践的なデータ処理に対応できるようになります。
データベースやSQLの知識を深め、実務で使える技術として身につけたい方にとって、PostgreSQLの正規表現は学ぶ価値の高いテーマです。当社では、こうしたデータベース設計・SQL改善・システム運用に関心を持ち、技術を現場で活かしていきたい方と一緒に働く仲間を探しています。技術を学びながら実務で成長したい方は、ぜひ当社の求人情報もご覧ください。
学んだSQLを、実務で使えるスキルにしたい方へ
本記事ではSQLの基本的な考え方や使い方を解説しましたが、
「実務で使えるレベルまで身につけたい」と感じた方も多いのではないでしょうか。
SQLは、文法を理解するだけでなく、
- どんなデータ構造で使われるのか
- どんなクエリが現場で求められるのか
を意識して学ぶことで、実践力が大きく変わります。
そうした「実務を見据えたSQL学習」を進めたい方には、
完全無料で学べるプログラミングスクール ZeroCode PLUS という選択肢もあります。
- SQLを含むWeb・データベース系スキルを体系的に学べる
- 未経験者でも実務を意識したカリキュラム
- 受講料・教材費がかからない完全無料の学習環境
- 完全オンラインでスキマ学習
※学習内容や進め方を確認するだけでもOKです