【Oracle】正規表現(REGEXP)関数の使い方完全ガイド|REGEXP_LIKE・REGEXP_REPLACE・REGEXP_SUBSTR・REGEXP_INSTR・REGEXP_COUNT

【Oracle】正規表現(REGEXP)関数の使い方完全ガイド|REGEXP_LIKE・REGEXP_REPLACE・REGEXP_SUBSTR・REGEXP_INSTR・REGEXP_COUNT Oracle

データ検証や文字列の抽出・加工で「LIKE演算子では対応できない複雑なパターンを扱いたい」という場面があります。そんなときに役立つのがOracleのREGEXP関数群です。Oracle 10g以降に導入されたこれらの関数はPOSIX準拠の正規表現をSQLから直接使えるようにしたもので、データクレンジング・バリデーション・ログ解析など幅広い用途に対応します。本記事では5つのREGEXP関数を構文・オプション・実務パターンまで体系的に解説します。

この記事でわかること

  • OracleのREGEXP関数5種の構文と使い分け
  • POSIX正規表現のメタ文字・文字クラス一覧
  • 大文字小文字を区別しないなど修飾子(マッチパラメータ)の使い方
  • REGEXP_LIKEによるWHERE条件での絞り込み
  • REGEXP_REPLACEによる文字列の置換・除去
  • REGEXP_SUBSTRによるパターンに一致した部分文字列の抽出
  • REGEXP_INSTR / REGEXP_COUNTの活用
  • メールアドレス検証・電話番号抽出・HTMLタグ除去など実務パターン
スポンサーリンク

OracleのREGEXP関数とは

Oracleは10g(10.1.0)以降、POSIX 1003.2準拠の正規表現をサポートするREGEXP関数群を提供しています。通常の LIKE 演算子では %(0文字以上の任意文字列)と _(任意の1文字)しか使えませんが、正規表現ではより細かいパターンを表現できます。

関数名 役割 戻り値
REGEXP_LIKE 文字列が正規表現にマッチするか判定 TRUE / FALSE(WHERE・CHECK制約で使用)
REGEXP_REPLACE マッチした部分を別の文字列に置換 置換後の文字列(VARCHAR2)
REGEXP_SUBSTR マッチした部分文字列を抽出 マッチした文字列(VARCHAR2)
REGEXP_INSTR マッチした部分の開始位置を取得 位置(NUMBER)
REGEXP_COUNT マッチした回数を取得 件数(NUMBER)

正規表現のメタ文字一覧

OracleのREGEXP関数で使える主なメタ文字です。

メタ文字 意味
. 任意の1文字(改行を除く) a.c → abc, aXc
* 直前の要素の0回以上の繰り返し ab* → a, ab, abb
+ 直前の要素の1回以上の繰り返し ab+ → ab, abb
? 直前の要素の0回または1回 colou?r → color, colour
{n} 直前の要素のちょうどn回 [0-9]{4} → 4桁の数字
{n,m} 直前の要素のn〜m回 [0-9]{2,4} → 2〜4桁
^ 文字列の先頭 ^ABC → ABCで始まる
$ 文字列の末尾 xyz$ → xyzで終わる
[...] 文字クラス(いずれか1文字) [aeiou] → 母音1文字
[^...] 否定文字クラス(含まれない1文字) [^0-9] → 数字以外
| OR(いずれかのパターン) cat|dog → cat または dog
() グループ化・キャプチャ (ab)+ → ab, abab
\d 数字([0-9]と同等) \d{3} → 3桁の数字
\w 英数字とアンダースコア \w+ → 1文字以上の単語
\s 空白文字(スペース・タブ・改行) \s+ → 1つ以上の空白

POSIXブラケット式(文字クラス)

Oracleの正規表現では [:class:] 形式のPOSIXブラケット式も使えます。マルチバイト文字(日本語など)を含む場合はこちらが安全です。

記法 意味
[:alpha:] アルファベット(A-Z, a-z)
[:digit:] 数字(0-9)
[:alnum:] 英数字([:alpha:]+[:digit:])
[:upper:] 大文字(A-Z)
[:lower:] 小文字(a-z)
[:space:] 空白文字
[:punct:] 句読点・記号

マッチパラメータ(修飾子)

各REGEXP関数の末尾に指定できるマッチパラメータで、パターンマッチの挙動を変えられます。

パラメータ 意味
i 大文字小文字を区別しない(case-insensitive)
c 大文字小文字を区別する(case-sensitive、デフォルト)
m 複数行モード。^$が各行の先頭・末尾にマッチ
n .が改行文字にもマッチする
x 空白とコメント(#以降)を無視(拡張モード)

REGEXP_LIKE

WHERE句やCHECK制約で使うパターンマッチ関数です。戻り値はTRUE/FALSEのため、SELECT の戻り値として使えず、条件式でのみ利用します。

構文:REGEXP_LIKE(source_char, pattern [, match_param])

REGEXP_LIKE ── 基本的な使い方
-- 数字のみで構成される行を抽出
SELECT employee_id, phone_number
FROM   employees
WHERE  REGEXP_LIKE(phone_number, '^[0-9]+$');

-- アルファベットで始まる名前(大文字小文字不問)
SELECT first_name
FROM   employees
WHERE  REGEXP_LIKE(first_name, '^[a-z]', 'i');  -- 'i' = 大文字小文字を区別しない

-- ひらがな・カタカナを含む行を除外
SELECT customer_name
FROM   customers
WHERE  NOT REGEXP_LIKE(customer_name, '[[:alpha:]]');
REGEXP_LIKE ── CHECK制約でのバリデーション
-- メールアドレス形式のCHECK制約
ALTER TABLE users
    ADD CONSTRAINT chk_email_format
    CHECK (REGEXP_LIKE(email, '^[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}$'));

-- 郵便番号(7桁数字またはハイフンあり形式)のCHECK制約
ALTER TABLE addresses
    ADD CONSTRAINT chk_zip_format
    CHECK (REGEXP_LIKE(zip_code, '^[0-9]{3}-?[0-9]{4}$'));

REGEXP_REPLACE

パターンにマッチした部分を別の文字列に置換します。第3引数で空文字列を指定すれば、マッチした部分を削除できます。

構文:REGEXP_REPLACE(source_char, pattern [, replace_string [, position [, occurrence [, match_param]]]])

引数 説明 デフォルト
source_char 検索対象の文字列
pattern 正規表現パターン
replace_string 置換後の文字列(省略時はNULL) NULL
position 検索開始位置(1始まり) 1
occurrence 何番目のマッチを置換するか(0=全て) 0
match_param 修飾子(i, c, m, n, x) なし
REGEXP_REPLACE ── 基本的な置換
-- 数字以外の文字を全て除去(電話番号のハイフン・括弧を取り除く)
SELECT
    phone_raw,
    REGEXP_REPLACE(phone_raw, '[^0-9]', '') AS phone_digits_only
FROM (
    SELECT '090-1234-5678' AS phone_raw FROM dual UNION ALL
    SELECT '(03)1234-5678' FROM dual UNION ALL
    SELECT '0312345678'    FROM dual
);
-- 結果: 09012345678 / 0312345678 / 0312345678
REGEXP_REPLACE ── 空白の正規化と特定パターンの除去
-- 連続する空白を1つにまとめる
SELECT REGEXP_REPLACE('Hello   World   !', '\s+', ' ') AS normalized
FROM   dual;
-- 結果: 'Hello World !'

-- HTMLタグを除去する
SELECT REGEXP_REPLACE(
    '太郎さんへ',
    '<[^>]+>',   -- < から始まり > で終わるHTMLタグにマッチ
    ''           -- 空文字で置換(削除)
) AS plain_text
FROM   dual;
-- 結果: '太郎さんへ'

-- 先頭・末尾の空白を削除(TRIMと同等だが正規表現版)
SELECT REGEXP_REPLACE('  hello world  ', '^\s+|\s+$', '') AS trimmed
FROM   dual;
-- 結果: 'hello world'
REGEXP_REPLACE ── 後方参照(キャプチャグループの再利用)
-- 後方参照を使って日付形式を変換(YYYYMMDD → YYYY/MM/DD)
SELECT
    REGEXP_REPLACE('20260328', '^([0-9]{4})([0-9]{2})([0-9]{2})$', '//')
        AS formatted_date
FROM   dual;
-- 結果: '2026/03/28'

-- 氏名の「姓名」順を「名姓」に入れ替え
SELECT
    REGEXP_REPLACE('Yamada Taro', '^(\S+)\s+(\S+)$', ' ') AS swapped
FROM   dual;
-- 結果: 'Taro Yamada'

後方参照(バックリファレンス)では \9 でキャプチャグループを参照します。これは通常の REPLACE 関数にはない強力な機能です。改行コードの置換については【Oracle】改行コードを置換・削除する方法完全ガイドも参照してください。

REGEXP_SUBSTR

パターンにマッチした部分文字列を返します。マッチしない場合は NULL を返します。

構文:REGEXP_SUBSTR(source_char, pattern [, position [, occurrence [, match_param [, subexpr]]]])

引数 説明 デフォルト
position 検索開始位置(1始まり) 1
occurrence 何番目のマッチを返すか 1
match_param 修飾子 なし
subexpr 返すキャプチャグループの番号(0=マッチ全体) 0
REGEXP_SUBSTR ── 基本的な抽出
-- 文字列から最初の数値を抽出
SELECT
    REGEXP_SUBSTR('Order #12345 shipped', '[0-9]+') AS order_num
FROM   dual;
-- 結果: '12345'

-- 2番目のマッチを取得(occurrence=2)
SELECT
    REGEXP_SUBSTR('abc123def456ghi', '[0-9]+', 1, 2) AS second_num
FROM   dual;
-- 結果: '456'

-- ドメイン名だけを抽出(@以降の部分)
SELECT
    REGEXP_SUBSTR(email, '@(.+)$', 1, 1, 'i', 1) AS domain
FROM   users;
-- subexpr=1 で1番目のキャプチャグループを返す
REGEXP_SUBSTR ── カンマ区切りの値を分割する
-- CSV形式の文字列から各要素を取り出す(occurrence を変えながらSELECT)
SELECT
    REGEXP_SUBSTR('apple,banana,cherry,date', '[^,]+', 1, 1) AS item1,
    REGEXP_SUBSTR('apple,banana,cherry,date', '[^,]+', 1, 2) AS item2,
    REGEXP_SUBSTR('apple,banana,cherry,date', '[^,]+', 1, 3) AS item3,
    REGEXP_SUBSTR('apple,banana,cherry,date', '[^,]+', 1, 4) AS item4
FROM   dual;
-- 結果: apple / banana / cherry / date
REGEXP_SUBSTR ── メールアドレスのローカル部とドメインを分離
SELECT
    email,
    REGEXP_SUBSTR(email, '^[^@]+')        AS local_part,   -- @より前
    REGEXP_SUBSTR(email, '[^@]+$')        AS domain_part   -- @より後
FROM   users
WHERE  REGEXP_LIKE(email, '^[^@]+@[^@]+\.[^@]+$');  -- 有効なメール形式のみ

REGEXP_INSTR

パターンにマッチした部分の開始位置(または終了位置の次)を返します。マッチしない場合は0を返します。

構文:REGEXP_INSTR(source_char, pattern [, position [, occurrence [, return_opt [, match_param [, subexpr]]]]])

return_opt に 0 を指定するとマッチ開始位置、1 を指定するとマッチ終了位置の次を返します。

REGEXP_INSTR ── パターンの位置を取得する
-- 最初の数字の開始位置を取得
SELECT
    REGEXP_INSTR('Price: 1980 yen', '[0-9]+') AS pos
FROM   dual;
-- 結果: 8 ('1'の位置)

-- マッチ終了の次の位置を取得(return_opt=1)
SELECT
    REGEXP_INSTR('Price: 1980 yen', '[0-9]+', 1, 1, 1) AS pos_after
FROM   dual;
-- 結果: 12 ('0'の次)

-- IPアドレスの第2オクテットの開始位置
SELECT
    REGEXP_INSTR('192.168.0.1', '[0-9]+', 1, 2) AS second_octet_pos
FROM   dual;
-- 結果: 5 ('168'の開始位置)

-- 特定パターンが存在するかどうかの確認(0 = 存在しない)
SELECT
    CASE
        WHEN REGEXP_INSTR(description, '<script', 1, 1, 0, 'i') > 0
        THEN 'XSS疑い'
        ELSE 'OK'
    END AS security_check
FROM   articles;

REGEXP_COUNT

パターンがマッチした回数を返します。Oracle 11g Release 1以降で使用可能です。

構文:REGEXP_COUNT(source_char, pattern [, position [, match_param]])

REGEXP_COUNT ── パターンの出現回数を数える
-- 文字列中の数字の塊の数を数える
SELECT
    REGEXP_COUNT('abc123def456ghi789', '[0-9]+') AS num_groups
FROM   dual;
-- 結果: 3

-- カンマの数(要素数 - 1)を数える
SELECT
    product_code,
    REGEXP_COUNT(tags, ',') + 1 AS tag_count
FROM   products;

-- 特定の単語が何回登場するか
SELECT
    REGEXP_COUNT(description, 'Oracle', 1, 'i') AS oracle_mentions
FROM   articles;
--  は単語境界(単語の境界を示すアサーション)
REGEXP_COUNT は Oracle 11g Release 1(11.1.0)以降
REGEXP_LIKEとREGEXP_REPLACE・REGEXP_SUBSTR・REGEXP_INSTRは Oracle 10g(10.1.0)から使えますが、REGEXP_COUNTは Oracle 11g Release 1(11.1.0)以降で追加されました。古い環境では使用できないため、バージョンに応じて代替手段(LENGTH(REGEXP_REPLACE(src, pattern, ”))で文字を消した長さの差分など)を使います。

実務でよく使うパターン

メールアドレスの形式チェックと抽出

メールアドレスの検証と抽出
-- 正規表現によるメールアドレスバリデーション
SELECT
    email,
    CASE
        WHEN REGEXP_LIKE(email,
             '^[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}$')
        THEN '有効'
        ELSE '無効'
    END AS email_status
FROM   users;

-- ドメインだけを一覧で集計
SELECT
    REGEXP_SUBSTR(email, '@(.+)$', 1, 1, NULL, 1) AS domain,
    COUNT(*) AS user_count
FROM   users
WHERE  REGEXP_LIKE(email, '@')
GROUP BY REGEXP_SUBSTR(email, '@(.+)$', 1, 1, NULL, 1)
ORDER BY user_count DESC;

電話番号の正規化

電話番号の正規化(ハイフン統一・数字のみ抽出)
-- 様々な形式の電話番号を数字のみにする
SELECT
    phone_raw,
    REGEXP_REPLACE(phone_raw, '[^0-9]', '') AS digits_only
FROM (
    SELECT '090-1234-5678' AS phone_raw FROM dual UNION ALL
    SELECT '(090)1234 5678'             FROM dual UNION ALL
    SELECT '090.1234.5678'              FROM dual UNION ALL
    SELECT '09012345678'                FROM dual
);

-- ハイフン区切り形式に統一(11桁の携帯番号)
SELECT
    REGEXP_REPLACE(
        REGEXP_REPLACE(phone_raw, '[^0-9]', ''),   -- まず数字だけにする
        '^([0-9]{3})([0-9]{4})([0-9]{4})$',        -- 3-4-4 に分割
        '--'
    ) AS formatted_phone
FROM   customers;

郵便番号の検証

郵便番号の検証(ハイフンあり・なし両対応)
-- 〒123-4567 / 1234567 どちらも許可するバリデーション
SELECT
    zip_code,
    CASE
        WHEN REGEXP_LIKE(zip_code, '^[0-9]{3}-?[0-9]{4}$')
        THEN '正常'
        ELSE '不正'
    END AS zip_status
FROM   addresses;

-- ハイフンなしに統一する
SELECT
    REGEXP_REPLACE(zip_code, '-', '') AS zip_normalized
FROM   addresses
WHERE  REGEXP_LIKE(zip_code, '^[0-9]{3}-?[0-9]{4}$');

HTMLタグ・制御文字の除去

HTMLタグと制御文字の除去
-- HTMLタグを全て除去してプレーンテキストに変換
SELECT
    REGEXP_REPLACE(html_content, '<[^>]+>', '') AS plain_text
FROM   articles;

-- 制御文字(タブ・改行・復帰)を除去
SELECT
    REGEXP_REPLACE(raw_text, '[[:cntrl:]]', '') AS clean_text
FROM   import_data;

-- 英数字・スペース以外の文字を除去(記号をすべて削除)
SELECT
    REGEXP_REPLACE(user_input, '[^[:alnum:] ]', '') AS safe_text
FROM   user_comments;

ログ解析・文字列の分解

アクセスログから各要素を抽出
-- アクセスログ例: "192.168.1.100 - [28/Mar/2026:10:30:00] GET /index.html 200"
SELECT
    log_line,
    REGEXP_SUBSTR(log_line, '^[0-9.]+')                        AS ip_address,
    REGEXP_SUBSTR(log_line, '\[([^\]]+)\]', 1, 1, NULL, 1)    AS access_time,
    REGEXP_SUBSTR(log_line, '(GET|POST|PUT|DELETE) \S+', 1, 1) AS method_path,
    REGEXP_SUBSTR(log_line, ' ([0-9]{3})$', 1, 1, NULL, 1)    AS status_code
FROM   access_logs;

LIKE vs REGEXP_LIKE の使い分け

比較項目 LIKE REGEXP_LIKE
パターンの柔軟性 % と _ のみ POSIX正規表現フル対応
パフォーマンス インデックスを活用しやすい 全件スキャンになりやすい
可読性 シンプル 複雑なパターンを簡潔に書ける
推奨ケース 前方一致・後方一致など単純なパターン 文字クラス・繰り返し・選択など複雑なパターン
パフォーマンスに注意
REGEXP関数はWHERE句に使うとインデックスが効かず全件スキャンになる場合がほとんどです。大量データへの適用は夜間バッチやデータクレンジング用途に限定し、頻繁に参照されるオンラインクエリへの無制限な適用は避けてください。文字列操作関数の詳細は【Oracle】SUBSTR()関数で文字列の一部を切り出す方法【Oracle】文字列の文字数・バイト数を取得する方法も参考にしてください。

まとめ

OracleのREGEXP関数群は5種類あり、それぞれ役割が異なります。

  • REGEXP_LIKE:WHERE句・CHECK制約でパターンマッチ判定。入力バリデーションに最適
  • REGEXP_REPLACE:マッチした文字列を置換・削除。後方参照でフォーマット変換も可能
  • REGEXP_SUBSTR:マッチした部分を抽出。subexpr引数でキャプチャグループも取れる
  • REGEXP_INSTR:マッチした位置番号を返す。存在チェックや部分文字列のオフセット計算に使う
  • REGEXP_COUNT:出現回数を返す(11g R1以降)。パターンの頻度分析に便利
  • パフォーマンス:WHERE句での使用はインデックスが使われないため、大量データへの適用は慎重に

LIKE演算子で対応できない複雑なパターン検証・データクレンジングにはREGEXP関数を積極的に活用し、シンプルな前方一致・後方一致はLIKEを使うという使い分けが実務での鉄則です。DECODE関数など他の文字列操作との組み合わせ方は【Oracle】条件に合致する場合に別の値を返すDECODE関数の使い方も参照してください。