【Oracle】TRIM / LTRIM / RTRIM 完全ガイド|全角スペース・タブ・制御文字の削除・REGEXP_REPLACE・一括クリーニングまで解説

【Oracle】TRIM / LTRIM / RTRIM 完全ガイド|全角スペース・タブ・制御文字の削除・REGEXP_REPLACE・一括クリーニングまで解説 Oracle

Oracle でカラムの前後にある余分な空白を除去するには TRIMLTRIMRTRIM 関数を使います。しかし「TRIM で全角スペースが消えない」「LTRIMTRIM(LEADING ...) は何が違うのか」「タブや制御文字を一括で除去したい」といった疑問にぶつかることは多いものです。

本記事では、TRIM・LTRIM・RTRIM の構文と仕様の違いを整理したうえで、全角スペース(U+3000)の削除方法タブ・改行・制御文字の除去パターンREGEXP_REPLACE を使った高度な空白除去、そして UPDATE による既存データの一括クリーニングまで体系的に解説します。

この記事でわかること
・TRIM 関数の基本(LEADING / TRAILING / BOTH の使い分け)
・LTRIM / RTRIM 関数の使い方と TRIM との仕様差
・TRIM では削除できない全角スペースの対処法
・タブ(CHR(9))・改行(CHR(10)/CHR(13))の除去方法
・REGEXP_REPLACE で空白系文字を一括除去するパターン
・UPDATE での既存データ一括クリーニング手順
・TRIM / REPLACE / REGEXP_REPLACE のパフォーマンス比較
・実践パターン:検索条件での空白吸収・データ移行時のクレンジング
スポンサーリンク

TRIM 関数の基本

TRIM 関数は文字列の先頭・末尾(またはその両方)から1 種類の文字を除去します。省略時は半角スペース(U+0020)が対象です。

SQL(TRIM 基本構文)
-- 構文
TRIM( [ LEADING | TRAILING | BOTH ] [ 除去する文字 FROM ] 文字列 )

-- 前後の半角スペースを除去(デフォルト: BOTH)
SELECT TRIM('  Hello World  ') AS result FROM dual;
-- 結果: 'Hello World'(中間のスペースは残る)

-- 先頭のみ除去(LEADING)
SELECT TRIM(LEADING ' ' FROM '  Hello  ') AS result FROM dual;
-- 結果: 'Hello  '

-- 末尾のみ除去(TRAILING)
SELECT TRIM(TRAILING ' ' FROM '  Hello  ') AS result FROM dual;
-- 結果: '  Hello'

指定した文字を除去する

SQL(TRIM で指定文字を除去)
-- 前後のハイフンを除去
SELECT TRIM('-' FROM '---Hello---') AS result FROM dual;
-- 結果: 'Hello'

-- 前後の 0(ゼロ)を除去
SELECT TRIM('0' FROM '00012300') AS result FROM dual;
-- 結果: '123'

-- LEADING で先頭のゼロのみ除去
SELECT TRIM(LEADING '0' FROM '00012300') AS result FROM dual;
-- 結果: '12300'
TRIM は「1 文字」しか指定できない
TRIM('ab' FROM 'abcba') はエラー(ORA-30001)になります。TRIM の除去対象は常に1 文字です。複数の文字を同時に除去したい場合は LTRIM/RTRIM を使います(後述)。

LTRIM / RTRIM 関数と TRIM との違い

LTRIM は先頭から、RTRIM は末尾から文字を除去します。TRIM との最大の違いは、「文字セット」(複数の文字)を指定できる点です。

SQL(LTRIM / RTRIM 基本構文)
-- 構文
LTRIM( 文字列 [, 除去する文字セット] )
RTRIM( 文字列 [, 除去する文字セット] )

-- 先頭の半角スペースを除去(文字セット省略時: 半角スペース)
SELECT LTRIM('  Hello  ') AS result FROM dual;
-- 結果: 'Hello  '

-- 末尾の半角スペースを除去
SELECT RTRIM('  Hello  ') AS result FROM dual;
-- 結果: '  Hello'

-- 前後の半角スペースを除去(LTRIM + RTRIM を組み合わせる)
SELECT LTRIM(RTRIM('  Hello  ')) AS result FROM dual;
-- 結果: 'Hello'

文字セット指定:複数の文字を同時に除去する

SQL(LTRIM / RTRIM の文字セット指定)
-- 先頭から 0 と スペース の両方を除去
SELECT LTRIM(' 00 123 ', ' 0') AS result FROM dual;
-- 結果: '123 '(先頭の ' ', '0', ' ' がすべて除去)

-- 末尾から複数文字を除去
SELECT RTRIM('Hello...!!!', '.!') AS result FROM dual;
-- 結果: 'Hello'

-- 先頭から a, b, c を除去
SELECT LTRIM('abcbaxyz', 'abc') AS result FROM dual;
-- 結果: 'xyz'(先頭から 'a','b','c','b','a' が順に除去される)
文字セット指定の動作原理
LTRIM / RTRIM の第 2 引数は「文字列」ではなく「文字の集合」です。先頭(末尾)から 1 文字ずつ調べ、その文字が文字セットに含まれていれば除去し、含まれていない文字が見つかった時点で停止します。「LTRIM('abcba', 'ab')」は先頭から「a→含む、b→含む、c→含まない→停止」で結果は 'cba' になります。

TRIM / LTRIM / RTRIM 比較表

項目 TRIM LTRIM RTRIM
除去位置 LEADING / TRAILING / BOTH を指定 先頭のみ 末尾のみ
除去文字 1 文字のみ指定可 複数文字(文字セット)指定可 複数文字(文字セット)指定可
デフォルト除去文字 半角スペース 半角スペース 半角スペース
全角スペース対応 除去する文字に指定すれば可能
(ただし半角と同時除去は不可)
文字セットに含めれば可能 文字セットに含めれば可能
戻り値が NULL 入力が NULL なら NULL 入力が NULL なら NULL 入力が NULL なら NULL

全角スペース(U+3000)の削除方法

TRIM(' ' FROM col) で全角スペースは除去できますが、半角スペースと全角スペースの両方を同時に除去したい場合、TRIM では 1 文字しか指定できないため対応できません。LTRIM / RTRIM または REPLACE / REGEXP_REPLACE を使います。

SQL(全角スペースの削除パターン)
-- パターン①: LTRIM + RTRIM で半角・全角スペースを同時除去
SELECT LTRIM(RTRIM(col, ' ' || CHR(12288)), ' ' || CHR(12288)) AS result
FROM your_table;
-- CHR(12288) = 全角スペース(U+3000)
-- 文字セットに半角スペース + 全角スペースを指定

-- パターン②: REPLACE で全角スペースを半角に統一してから TRIM
SELECT TRIM(REPLACE(col, CHR(12288), ' ')) AS result
FROM your_table;

-- パターン③: REGEXP_REPLACE で前後の空白系文字を一括除去
SELECT REGEXP_REPLACE(
    REGEXP_REPLACE(col, '^[[:space:]' || CHR(12288) || ']+', ''),
    '[[:space:]' || CHR(12288) || ']+$', ''
) AS result
FROM your_table;
全角スペースのコード表記
CHR(12288): 全角スペース(U+3000)を文字コード番号で指定
UNISTR('\3000'): Unicode コードポイントで指定(AL32UTF8 環境)
・SQL 中に直接全角スペース ' ' を書くこともできますが、見分けがつかないためバグの原因になります。CHR(12288) の使用を推奨します。

タブ・改行・制御文字の除去

CSV 取り込みや外部連携で混入しがちなタブ・改行・制御文字の除去パターンをまとめます。

文字 CHR() 値 説明
タブ CHR(9) 水平タブ(HT)
改行(LF) CHR(10) Line Feed(Unix 改行)
復帰(CR) CHR(13) Carriage Return
CRLF CHR(13) || CHR(10) Windows 改行
全角スペース CHR(12288) U+3000
NULL 文字 CHR(0) 文字列終端(混入することがある)
SQL(タブ・改行の除去パターン)
-- タブを半角スペースに置換
SELECT REPLACE(col, CHR(9), ' ') AS result FROM your_table;

-- 改行を除去(CR + LF 両方)
SELECT REPLACE(REPLACE(col, CHR(13), ''), CHR(10), '') AS result
FROM your_table;

-- タブ + 改行 + 全角スペースを一括で半角スペースに統一してから TRIM
SELECT TRIM(
    REPLACE(
    REPLACE(
    REPLACE(
    REPLACE(col,
        CHR(13), ''),
        CHR(10), ''),
        CHR(9), ' '),
        CHR(12288), ' ')
) AS result
FROM your_table;

改行コードの詳しい取り扱いについては「Oracle 改行コードを置換・削除する方法」を参照してください。

REGEXP_REPLACE で空白を一括除去する

REPLACE を何重にもネストするのが煩雑な場合は、REGEXP_REPLACE の正規表現パターンで一括処理できます。

SQL(REGEXP_REPLACE で先頭・末尾の空白系文字を除去)
-- 先頭の空白系文字を除去(半角スペース・タブ・改行・全角スペース)
SELECT REGEXP_REPLACE(col, '^[[:space:]]+', '') AS trimmed_leading
FROM your_table;

-- 末尾の空白系文字を除去
SELECT REGEXP_REPLACE(col, '[[:space:]]+$', '') AS trimmed_trailing
FROM your_table;

-- 前後の空白系文字を両方除去
SELECT REGEXP_REPLACE(
    REGEXP_REPLACE(col, '^[[:space:]]+', ''),
    '[[:space:]]+$', ''
) AS trimmed_both
FROM your_table;

-- 文字列内の連続スペースを 1 つに圧縮(中間のスペースも整理)
SELECT REGEXP_REPLACE(
    REGEXP_REPLACE(
        REGEXP_REPLACE(col, '^[[:space:]]+', ''),
        '[[:space:]]+$', ''
    ),
    '[[:space:]]+', ' '
) AS normalized
FROM your_table;
パターン 意味 使いどころ
^[[:space:]]+ 先頭の空白系文字(1文字以上) LTRIM 相当(全角スペース含む)
[[:space:]]+$ 末尾の空白系文字(1文字以上) RTRIM 相当(全角スペース含む)
[[:space:]]+ 連続する空白系文字 中間のスペースを 1 つに圧縮
[^[:print:]] 非印字文字(制御文字すべて) バイナリゴミ・制御文字の除去
[[:space:]] の範囲に注意
Oracle の POSIX クラス [[:space:]] は半角スペース・タブ・改行(CR/LF)・フォームフィード・垂直タブを含みます。ただし全角スペース(U+3000)が含まれるかは文字セット設定に依存します。AL32UTF8 環境では通常含まれますが、確実に除去したい場合は [[:space:]||CHR(12288)||'] のように明示的に追加してください。
正規表現の詳細は「Oracle正規表現完全ガイド」を参照してください。

UPDATE による既存データの一括クリーニング

既にテーブルに格納されたデータの前後空白を一括除去する手順を説明します。

SQL(UPDATE で前後の空白を一括除去)
-- ステップ 1: 対象データの確認(更新前に必ず確認)
SELECT id, name,
       LENGTH(name)       AS before_len,
       LENGTH(TRIM(name)) AS after_len
FROM employees
WHERE name <> TRIM(name)     -- 前後に空白がある行だけ
   OR name IS NULL;          -- NULL の確認も

-- ステップ 2: UPDATE(半角スペースのみの除去)
UPDATE employees
SET name = TRIM(name)
WHERE name <> TRIM(name);

-- ステップ 3: COMMIT(問題なければ確定)
COMMIT;
SQL(全角スペース・タブも含めた包括クリーニング)
-- 全角スペース + タブ + 改行 + 半角スペースを一括除去
UPDATE employees
SET name = REGEXP_REPLACE(
    REGEXP_REPLACE(name, '^[[:space:]]+', ''),
    '[[:space:]]+$', ''
)
WHERE REGEXP_LIKE(name, '^[[:space:]]|[[:space:]]$');

-- 複数カラムを同時にクリーニング
UPDATE customers
SET first_name = TRIM(first_name),
    last_name  = TRIM(last_name),
    email      = LOWER(TRIM(email))   -- ついでに小文字化
WHERE first_name <> TRIM(first_name)
   OR last_name  <> TRIM(last_name)
   OR email      <> LOWER(TRIM(email));
UPDATE 前の確認を忘れない
・対象行数を事前に SELECT で確認してください
・件数が多い場合は ROWNUM で範囲を区切ってバッチ処理する
・CLOB 型のカラムには TRIM が直接使えません。DBMS_LOB.SUBSTR または REGEXP_REPLACE を使います
・本番環境では必ずバックアップを取ってから実行してください

パフォーマンス比較

空白除去に使える 3 つの関数のパフォーマンス特性を比較します。

関数 処理速度 対応範囲 使いどころ
TRIM / LTRIM / RTRIM 最速 半角スペースのみ(指定文字は 1 種類 / 文字セット) 半角スペースの除去で十分な場合(大多数のケース)
REPLACE 速い 指定した文字列を全置換(位置を問わない) 全角→半角変換や特定文字の除去に使う
REGEXP_REPLACE 遅い(TRIM の数倍〜数十倍) 正規表現で柔軟なパターンマッチ 複雑なパターン除去が必要な場合のみ使用
SQL(パフォーマンスの実測イメージ)
-- 大量データでの処理速度比較(10万行を想定)
-- 方法①: TRIM(最速)
SELECT TRIM(name) FROM large_table;              -- 例: 0.3秒

-- 方法②: LTRIM + RTRIM(TRIM とほぼ同等)
SELECT LTRIM(RTRIM(name)) FROM large_table;      -- 例: 0.35秒

-- 方法③: REPLACE(やや遅い)
SELECT TRIM(REPLACE(name, CHR(12288), ' ')) FROM large_table;  -- 例: 0.5秒

-- 方法④: REGEXP_REPLACE(最も遅い)
SELECT REGEXP_REPLACE(
    REGEXP_REPLACE(name, '^[[:space:]]+', ''),
    '[[:space:]]+$', ''
) FROM large_table;                              -- 例: 2.0秒
使い分けの判断基準
半角スペースの前後除去TRIM(最速・シンプル)
半角 + 全角スペースの前後除去LTRIM(RTRIM(col, ' ' || CHR(12288)), ' ' || CHR(12288))
タブ・改行含む全空白の除去REGEXP_REPLACE(遅いが確実)
大量データの UPDATE では REGEXP_REPLACE は避け、REPLACE + TRIM の組み合わせを推奨します。

実践パターン集

パターン①:WHERE 句での空白吸収検索

SQL(検索条件で空白を吸収する)
-- ユーザー入力に余分なスペースが含まれていても検索できるようにする
SELECT * FROM employees
WHERE TRIM(name) = TRIM(:input_name);

-- 部分一致検索でも前後スペースを吸収
SELECT * FROM employees
WHERE UPPER(TRIM(name)) LIKE '%' || UPPER(TRIM(:input_name)) || '%';

-- インデックスを活かしたい場合: 関数ベースインデックスを作成
CREATE INDEX idx_emp_name_trim ON employees (TRIM(name));
-- このインデックスがあれば WHERE TRIM(name) = ... でインデックスが使われる

パターン②:INSERT / UPDATE トリガーで自動クリーニング

SQL(トリガーで挿入時に自動 TRIM)
CREATE OR REPLACE TRIGGER trg_emp_name_trim
BEFORE INSERT OR UPDATE ON employees
FOR EACH ROW
BEGIN
    :NEW.name := TRIM(:NEW.name);
    :NEW.email := LOWER(TRIM(:NEW.email));
END;
/

-- これ以降、INSERT / UPDATE 時に自動的にスペースが除去される
INSERT INTO employees (id, name, email) VALUES (1, '  Tanaka  ', '  TANAKA@EXAMPLE.COM  ');
-- → name='Tanaka', email='tanaka@example.com' として格納

パターン③:CASE 文と組み合わせた条件付きクリーニング

SQL(条件付きクリーニング)
-- スペースのみの文字列を NULL に変換
SELECT
    id,
    CASE WHEN TRIM(name) IS NULL THEN NULL
         ELSE TRIM(name)
    END AS cleaned_name
FROM employees;

-- NULLIF + TRIM: 空文字列を NULL に変換(よりシンプル)
SELECT NULLIF(TRIM(name), '') AS cleaned_name
FROM employees;

-- NVL + TRIM: NULL を空文字列に変換してから TRIM
SELECT TRIM(NVL(name, '')) AS safe_name
FROM employees;

パターン④:データ移行時の一括クレンジング

SQL(INSERT … SELECT でクリーニングしながらコピー)
-- 旧テーブルから新テーブルへ空白を除去しながらコピー
INSERT INTO new_employees (id, name, department, email)
SELECT
    id,
    TRIM(REPLACE(REPLACE(REPLACE(name,
        CHR(9), ''), CHR(13), ''), CHR(10), '')),   -- タブ・改行除去 + TRIM
    TRIM(department),
    LOWER(TRIM(email))
FROM old_employees
WHERE name IS NOT NULL;

よくある質問

QTRIM で全角スペースが削除されません
ATRIM のデフォルトの除去対象は半角スペース(U+0020)です。全角スペース(U+3000)を除去するには TRIM(CHR(12288) FROM col) と指定するか、LTRIM(RTRIM(col, ' ' || CHR(12288)), ' ' || CHR(12288)) で半角・全角を同時に除去してください。
QTRIM(NULL) はエラーになりますか?
Aエラーにはなりません。TRIM(NULL)NULL を返します。LTRIM(NULL)RTRIM(NULL) も同様に NULL を返します。NULL 安全な関数なので、NVL などで事前に NULL チェックをする必要はありません。
QTRIM に複数の文字(’ab’)を指定するとエラーになります
ATRIM の除去対象は1 文字のみです。2 文字以上を指定すると ORA-30001 が発生します。複数の文字を同時に除去したい場合は LTRIM/RTRIM を使ってください。LTRIM(col, 'ab') は先頭から ‘a’ と ‘b’ のいずれかに該当する文字を除去し続けます。
QTRIM と REPLACE の違いは何ですか?
ATRIM先頭と末尾の文字のみを除去します。文字列の中間にあるスペースはそのまま残ります。REPLACE文字列内のすべての位置で指定文字列を置換・除去します。「前後のスペースだけ消したい」場合は TRIM、「文字列内のすべてのスペースを消したい」場合は REPLACE を使います。
QVARCHAR2 型にスペースのみの値が入っていると LENGTH は何を返しますか?
ALENGTH(' ') は 3 を返します(スペース 3 文字)。ただし Oracle では 空文字列は NULL として扱われるため、LENGTH('') は NULL を返します。TRIM(' ') は空文字列(= NULL)を返すので、LENGTH(TRIM(' ')) も NULL になります。
QCLOB 型のカラムに TRIM は使えますか?
ATRIMLTRIMRTRIM は VARCHAR2 型を受け取る関数です。CLOB を直接渡すと暗黙変換が走り、32767 バイトを超えるとエラーになります。CLOB の空白除去には REGEXP_REPLACE を使うか、DBMS_LOB.SUBSTR で部分的に取り出してから処理してください。

まとめ

Oracle の空白削除方法の要点をまとめます。

やりたいこと 使う関数・構文
前後の半角スペースを除去 TRIM(col)
先頭の半角スペースのみ除去 LTRIM(col) または TRIM(LEADING FROM col)
末尾の半角スペースのみ除去 RTRIM(col) または TRIM(TRAILING FROM col)
前後の指定した 1 文字を除去 TRIM(‘0’ FROM col)
前後の複数種類の文字を除去 LTRIM(RTRIM(col, ‘ 0-‘), ‘ 0-‘)
前後の半角 + 全角スペースを除去 LTRIM(RTRIM(col, ‘ ‘ || CHR(12288)), ‘ ‘ || CHR(12288))
タブ・改行を除去 REPLACE(REPLACE(col, CHR(9), ”), CHR(10), ”)
全空白系文字を一括除去(前後のみ) REGEXP_REPLACE(col, ‘^[[:space:]]+|[[:space:]]+$’, ”)
中間の連続スペースを 1 つに圧縮 REGEXP_REPLACE(col, ‘[[:space:]]+’, ‘ ‘)
空白のみの値を NULL に変換 NULLIF(TRIM(col), ”)

SQL 全般の TRIM 関数(RDBMS 間の構文差異など)については「SQL でスペースを削除する方法」、改行コードの詳しい取り扱いは「Oracle 改行コードを置換・削除する方法」、正規表現の詳細は「Oracle 正規表現完全ガイド」も併せて参照してください。