Oracle でカラムの前後にある余分な空白を除去するには TRIM・LTRIM・RTRIM 関数を使います。しかし「TRIM で全角スペースが消えない」「LTRIM と TRIM(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)が対象です。
-- 構文
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'
指定した文字を除去する
-- 前後のハイフンを除去
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('ab' FROM 'abcba') はエラー(ORA-30001)になります。TRIM の除去対象は常に1 文字です。複数の文字を同時に除去したい場合は LTRIM/RTRIM を使います(後述)。LTRIM / RTRIM 関数と TRIM との違い
LTRIM は先頭から、RTRIM は末尾から文字を除去します。TRIM との最大の違いは、「文字セット」(複数の文字)を指定できる点です。
-- 構文
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'
文字セット指定:複数の文字を同時に除去する
-- 先頭から 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 を使います。
-- パターン①: 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) | 文字列終端(混入することがある) |
-- タブを半角スペースに置換
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 の正規表現パターンで一括処理できます。
-- 先頭の空白系文字を除去(半角スペース・タブ・改行・全角スペース)
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:]] | 非印字文字(制御文字すべて) | バイナリゴミ・制御文字の除去 |
Oracle の POSIX クラス
[[:space:]] は半角スペース・タブ・改行(CR/LF)・フォームフィード・垂直タブを含みます。ただし全角スペース(U+3000)が含まれるかは文字セット設定に依存します。AL32UTF8 環境では通常含まれますが、確実に除去したい場合は [[:space:]||CHR(12288)||'] のように明示的に追加してください。正規表現の詳細は「Oracle正規表現完全ガイド」を参照してください。
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;
-- 全角スペース + タブ + 改行 + 半角スペースを一括除去
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));
・対象行数を事前に SELECT で確認してください
・件数が多い場合は ROWNUM で範囲を区切ってバッチ処理する
・CLOB 型のカラムには TRIM が直接使えません。
DBMS_LOB.SUBSTR または REGEXP_REPLACE を使います・本番環境では必ずバックアップを取ってから実行してください
パフォーマンス比較
空白除去に使える 3 つの関数のパフォーマンス特性を比較します。
| 関数 | 処理速度 | 対応範囲 | 使いどころ |
|---|---|---|---|
| TRIM / LTRIM / RTRIM | 最速 | 半角スペースのみ(指定文字は 1 種類 / 文字セット) | 半角スペースの除去で十分な場合(大多数のケース) |
| REPLACE | 速い | 指定した文字列を全置換(位置を問わない) | 全角→半角変換や特定文字の除去に使う |
| REGEXP_REPLACE | 遅い(TRIM の数倍〜数十倍) | 正規表現で柔軟なパターンマッチ | 複雑なパターン除去が必要な場合のみ使用 |
-- 大量データでの処理速度比較(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 句での空白吸収検索
-- ユーザー入力に余分なスペースが含まれていても検索できるようにする 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 トリガーで自動クリーニング
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 文と組み合わせた条件付きクリーニング
-- スペースのみの文字列を 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;
パターン④:データ移行時の一括クレンジング
-- 旧テーブルから新テーブルへ空白を除去しながらコピー
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;
よくある質問
TRIM のデフォルトの除去対象は半角スペース(U+0020)です。全角スペース(U+3000)を除去するには TRIM(CHR(12288) FROM col) と指定するか、LTRIM(RTRIM(col, ' ' || CHR(12288)), ' ' || CHR(12288)) で半角・全角を同時に除去してください。TRIM(NULL) は NULL を返します。LTRIM(NULL)・RTRIM(NULL) も同様に NULL を返します。NULL 安全な関数なので、NVL などで事前に NULL チェックをする必要はありません。TRIM の除去対象は1 文字のみです。2 文字以上を指定すると ORA-30001 が発生します。複数の文字を同時に除去したい場合は LTRIM/RTRIM を使ってください。LTRIM(col, 'ab') は先頭から ‘a’ と ‘b’ のいずれかに該当する文字を除去し続けます。TRIM は先頭と末尾の文字のみを除去します。文字列の中間にあるスペースはそのまま残ります。REPLACE は文字列内のすべての位置で指定文字列を置換・除去します。「前後のスペースだけ消したい」場合は TRIM、「文字列内のすべてのスペースを消したい」場合は REPLACE を使います。LENGTH(' ') は 3 を返します(スペース 3 文字)。ただし Oracle では 空文字列は NULL として扱われるため、LENGTH('') は NULL を返します。TRIM(' ') は空文字列(= NULL)を返すので、LENGTH(TRIM(' ')) も NULL になります。TRIM・LTRIM・RTRIM は 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 正規表現完全ガイド」も併せて参照してください。

