【Oracle】改行コードを置換・削除する方法完全ガイド|REPLACE・REGEXP_REPLACE・UPDATE実行・CLOB対応・確認方法まで

【Oracle】不要な改行コードを置換・削除する方法 Oracle

Oracleデータベースで外部システムから取り込んだデータや、アプリケーションが挿入したデータに改行コードが混入しているケースは多くあります。改行コードが含まれると、CSVエクスポートの列ずれ・SQL文字列比較の不一致・画面表示の乱れなどの問題が発生します。

この記事では、改行コードの確認方法から、REPLACE・REGEXP_REPLACEでの削除・置換UPDATEで実際にDBのデータを更新する方法CLOB型への対応まで、実務で使えるパターンを網羅します。

この記事でわかること
・改行コード CHR(10)・CHR(13) の種類と違い
・DUMP関数で改行コードの存在を確認する方法
・改行コードを含む行をSELECTで検索する方法
・REPLACE関数で改行コードを削除・スペースに置換する方法
・REGEXP_REPLACE関数で正規表現を使って柔軟に処理する方法
・UPDATEで実際にデータを更新する方法(安全な実行手順付き)
・CLOB/NCLOB型の改行コード処理と注意点
・パフォーマンスを考慮したWHERE条件付き更新
スポンサーリンク
  1. 改行コードの種類と CHR 関数
  2. 改行コードの含まれている行を確認する方法
    1. INSTR関数で改行コードを含む行を検索する
    2. REGEXP_LIKE で正規表現で検索する
    3. DUMP関数で改行コードの種類を詳細確認する
    4. 件数を確認する
  3. REPLACE関数で改行コードを削除する
    1. LFのみ削除
    2. CRとLFを両方削除(CRLF対応)
    3. 削除せずスペースに置換する
  4. REGEXP_REPLACE関数で正規表現を使って削除する
    1. 基本: CR または LF を削除
    2. 改行コードをスペースに置換(連続改行は1つにまとめる)
    3. REPLACE vs REGEXP_REPLACE の使い分け
  5. UPDATEで実際にデータを更新する
    1. ステップ1:更新前に件数と内容を確認する
    2. ステップ2:UPDATEを実行する
    3. ステップ3:確認してCOMMIT
    4. 複数カラムを一括で更新する
  6. CLOB/NCLOB型の改行コード処理
    1. CLOB に対して REPLACE を使う
    2. 大きなCLOBを分割して更新する
  7. 前後の改行コードだけを削除する(LTRIM/RTRIM活用)
  8. パフォーマンスを考慮したWHERE条件付き更新
  9. 実務でよくある改行コード処理パターン
    1. CSV取込データのクレンジング
    2. 改行コードを含む行だけをエクスポートして確認する
    3. 改行コードをHTMLのタグに変換する(表示用)
  10. よくあるトラブルと解決法
    1. ケース1:REPLACE後もまだ改行コードが残る
    2. ケース2:REGEXP_REPLACE で ORA-22835 が発生する(CLOB)
    3. ケース3:WHERE条件なしでUPDATEしてしまった
    4. ケース4:NULLカラムに REPLACE を適用するとエラーになる
  11. よくある質問
  12. まとめ
  13. あわせて読みたい

改行コードの種類と CHR 関数

改行コードは文字コード(ASCII)で表されます。Oracleでは CHR() 関数でコードから文字を生成できます。

コード CHR関数 名称 主なOS 説明
10 CHR(10) LF (Line Feed) Unix/Linux/macOS ラインフィード。単体の改行コード。
13 CHR(13) CR (Carriage Return) 旧macOS キャリッジリターン。単体では旧macで使用。
13+10 CHR(13)||CHR(10) CRLF Windows CRとLFの組み合わせ。Windowsの標準改行コード。
Oracleでの改行コードの現実
WindowsアプリからOracleにデータを挿入するとCRLF(CHR(13)||CHR(10))が混入しやすい。CSVインポートやテキストファイル取込ではLF(CHR(10))が多い。両方が混在することもあるため、最初に確認してから処理しましょう。

改行コードの含まれている行を確認する方法

INSTR関数で改行コードを含む行を検索する

-- CHR(10)(LF)を含む行を検索
SELECT id, col_name
FROM your_table
WHERE INSTR(col_name, CHR(10)) > 0;

-- CHR(13)(CR)を含む行も検索
SELECT id, col_name
FROM your_table
WHERE INSTR(col_name, CHR(13)) > 0;
-- LFまたはCRを含む行を一度に検索
SELECT id, col_name
FROM your_table
WHERE INSTR(col_name, CHR(10)) > 0
   OR INSTR(col_name, CHR(13)) > 0;

REGEXP_LIKE で正規表現で検索する

-- LFまたはCRを含む行を正規表現で検索
SELECT id, col_name
FROM your_table
WHERE REGEXP_LIKE(col_name, CHR(10)||'|'||CHR(13));

DUMP関数で改行コードの種類を詳細確認する

DUMP 関数は文字列の各文字をASCIIコード(10進数)で表示します。改行コードの存在と種類を確認できます。

-- 特定の行のカラムをDUMPで確認
SELECT DUMP(col_name) AS dump_result
FROM your_table
WHERE id = 1;

-- 結果例
-- Typ=1 Len=13: 72,101,108,108,111,44,13,10,87,111,114,108,100
--                              ↑ 44(,)  ↑13=CR ↑10=LF
DUMP の読み方
10 → LF(ラインフィード)
13 → CR(キャリッジリターン)
13,10 と連続している → CRLF(Windows改行)
これで対象テーブルにどの改行コードが使われているか判断できます。

件数を確認する

-- 改行コードを含む件数を確認(更新前の確認に使う)
SELECT
    COUNT(*) AS total_rows,
    SUM(CASE WHEN INSTR(col_name, CHR(10))  > 0 THEN 1 ELSE 0 END) AS lf_rows,
    SUM(CASE WHEN INSTR(col_name, CHR(13))  > 0 THEN 1 ELSE 0 END) AS cr_rows,
    SUM(CASE WHEN INSTR(col_name, CHR(13)||CHR(10)) > 0 THEN 1 ELSE 0 END) AS crlf_rows
FROM your_table;

REPLACE関数で改行コードを削除する

REPLACE(文字列, 検索文字, 置換文字) で改行コードを空文字に置換(=削除)します。

LFのみ削除

SELECT REPLACE(col_name, CHR(10), '') AS cleaned
FROM your_table;

CRとLFを両方削除(CRLF対応)

-- CRとLFを両方削除(順番はどちらが先でもOK)
SELECT REPLACE(REPLACE(col_name, CHR(13), ''), CHR(10), '') AS cleaned
FROM your_table;

-- CRLFをまず削除してから残りのCR/LFを削除する方法(より厳密)
SELECT REPLACE(REPLACE(REPLACE(col_name, CHR(13)||CHR(10), ''), CHR(13), ''), CHR(10), '') AS cleaned
FROM your_table;

削除せずスペースに置換する

改行コードを削除すると単語が連続して読みにくくなる場合、スペースや区切り文字に置換する方法が有効です。

-- CRLFをスペースに置換(見やすい形にする)
SELECT REPLACE(REPLACE(col_name, CHR(13), ''), CHR(10), ' ') AS cleaned
FROM your_table;

-- 例: 結果
-- 変換前: 'Hello,\r\nWorld!'
-- 変換後: 'Hello, World!'

REGEXP_REPLACE関数で正規表現を使って削除する

REGEXP_REPLACE を使うと、[\r\n](CR または LF)を一度に処理できます。REPLACE のネストより可読性が高く、より柔軟な処理が可能です。

基本: CR または LF を削除

-- [\r\n] は CR または LF にマッチ
SELECT REGEXP_REPLACE(col_name, '[\r\n]', '') AS cleaned
FROM your_table;

-- + で連続する改行コードも1回で削除
SELECT REGEXP_REPLACE(col_name, '[\r\n]+', '') AS cleaned
FROM your_table;

改行コードをスペースに置換(連続改行は1つにまとめる)

-- 連続する改行コードを1つのスペースに置換
SELECT REGEXP_REPLACE(col_name, '[\r\n]+', ' ') AS cleaned
FROM your_table;

REPLACE vs REGEXP_REPLACE の使い分け

REPLACE REGEXP_REPLACE
構文 REPLACE(str, chr, replace) REGEXP_REPLACE(str, pattern, replace)
パフォーマンス 速い(固定文字列マッチ) やや遅い(正規表現エンジン)
可読性 ネストが深くなりやすい 1回でCR/LF両方を処理できる
柔軟性 固定文字列のみ 正規表現パターンが使える
CLOBへの適用 可(Oracle 11g以降) 可(Oracle 10g以降)
推奨場面 単純なLF/CR削除 複数パターン・連続改行処理

UPDATEで実際にデータを更新する

SELECT で確認してから UPDATE するのが安全な手順です。

ステップ1:更新前に件数と内容を確認する

-- 更新対象の件数を確認
SELECT COUNT(*)
FROM your_table
WHERE INSTR(col_name, CHR(10)) > 0 OR INSTR(col_name, CHR(13)) > 0;

-- 更新後の値をSELECTで確認
SELECT id, REPLACE(REPLACE(col_name, CHR(13), ''), CHR(10), '') AS preview
FROM your_table
WHERE INSTR(col_name, CHR(10)) > 0 OR INSTR(col_name, CHR(13)) > 0
AND ROWNUM <= 10;

ステップ2:UPDATEを実行する

-- REPLACE関数でLF・CRを削除
UPDATE your_table
SET col_name = REPLACE(REPLACE(col_name, CHR(13), ''), CHR(10), '')
WHERE INSTR(col_name, CHR(10)) > 0 OR INSTR(col_name, CHR(13)) > 0;

-- 更新件数の確認
SELECT SQL%ROWCOUNT FROM DUAL;  -- PL/SQL内の場合
-- REGEXP_REPLACEを使う場合
UPDATE your_table
SET col_name = REGEXP_REPLACE(col_name, '[\r\n]+', '')
WHERE REGEXP_LIKE(col_name, '[\r\n]');

ステップ3:確認してCOMMIT

-- 更新後の確認
SELECT id, col_name
FROM your_table
WHERE INSTR(col_name, CHR(10)) > 0 OR INSTR(col_name, CHR(13)) > 0;
-- 0件になれば成功

COMMIT;  -- 問題なければ確定
-- ROLLBACK;  -- 問題があれば取り消し
UPDATEは必ずトランザクション(COMMIT前に確認)で実行する
OracleのDMLは自動COMMITされません。COMMIT前であればROLLBACKで元に戻せます。必ず更新後にSELECTで結果を確認し、問題なければCOMMITしましょう。

複数カラムを一括で更新する

-- 複数カラムを1回のUPDATEで処理
UPDATE your_table
SET col1 = REPLACE(REPLACE(col1, CHR(13), ''), CHR(10), ''),
    col2 = REPLACE(REPLACE(col2, CHR(13), ''), CHR(10), ''),
    col3 = REGEXP_REPLACE(col3, '[\r\n]+', '')
WHERE INSTR(col1, CHR(10)) > 0
   OR INSTR(col1, CHR(13)) > 0
   OR INSTR(col2, CHR(10)) > 0
   OR INSTR(col2, CHR(13)) > 0
   OR INSTR(col3, CHR(10)) > 0
   OR INSTR(col3, CHR(13)) > 0;

CLOB/NCLOB型の改行コード処理

CLOB(大容量文字列型)は通常のVARCHAR2と同じように REPLACEREGEXP_REPLACE で処理できます(Oracle 11g以降)。ただしいくつかの注意点があります。

CLOB に対して REPLACE を使う

-- CLOBカラムの改行コードを削除
UPDATE your_table
SET clob_col = REPLACE(REPLACE(clob_col, CHR(13), ''), CHR(10), '')
WHERE INSTR(clob_col, CHR(10)) > 0 OR INSTR(clob_col, CHR(13)) > 0;
CLOBの注意点
・CLOBは最大4GBのデータを格納できるが、REPLACEの処理はメモリを大量消費することがある
・非常に大きなCLOBを一括更新するとUNDOセグメント不足(ORA-01555等)が発生することがある
・大量のCLOBを更新する場合は分割COMMIT(ROWID範囲やROWNUM指定)を検討する
REGEXP_REPLACE はCLOBのサイズが32767バイトを超えるとエラーになるケースがある(バージョン依存)

大きなCLOBを分割して更新する

-- ROWID範囲で分割して更新(ORA-01555対策)
DECLARE
    CURSOR c IS SELECT ROWID FROM your_table
                WHERE INSTR(clob_col, CHR(10)) > 0;
    v_rowid ROWID;
    v_count NUMBER := 0;
BEGIN
    OPEN c;
    LOOP
        FETCH c INTO v_rowid;
        EXIT WHEN c%NOTFOUND;

        UPDATE your_table
        SET clob_col = REPLACE(REPLACE(clob_col, CHR(13), ''), CHR(10), '')
        WHERE ROWID = v_rowid;

        v_count := v_count + 1;
        IF MOD(v_count, 1000) = 0 THEN
            COMMIT;
        END IF;
    END LOOP;
    COMMIT;
    CLOSE c;
    DBMS_OUTPUT.PUT_LINE('更新件数: ' || v_count);
END;
/

前後の改行コードだけを削除する(LTRIM/RTRIM活用)

文字列の先頭・末尾の改行コードだけを取り除きたい場合、LTRIM / RTRIM が使えます。

-- 先頭の改行コードを削除
SELECT LTRIM(col_name, CHR(10)||CHR(13)) AS cleaned
FROM your_table;

-- 末尾の改行コードを削除
SELECT RTRIM(col_name, CHR(10)||CHR(13)) AS cleaned
FROM your_table;

-- 先頭・末尾両方の改行コードを削除
SELECT TRIM(BOTH CHR(10) FROM TRIM(BOTH CHR(13) FROM col_name)) AS cleaned
FROM your_table;

パフォーマンスを考慮したWHERE条件付き更新

改行コードを含まない行にも REPLACE を適用すると処理時間と UNDO ログが増加します。WHERE句で改行コードを含む行のみに絞り込むことでパフォーマンスを改善できます。

-- NG: 全行に REPLACE を適用(無駄なUNDOが発生)
UPDATE your_table
SET col_name = REPLACE(REPLACE(col_name, CHR(13), ''), CHR(10), '');

-- OK: 改行コードを含む行のみ更新(パフォーマンス改善)
UPDATE your_table
SET col_name = REPLACE(REPLACE(col_name, CHR(13), ''), CHR(10), '')
WHERE INSTR(col_name, CHR(10)) > 0 OR INSTR(col_name, CHR(13)) > 0;
テーブルが大きい場合、col_name にファンクション索引(INSTR(col_name, CHR(10)))を作成するとWHERE句の検索が高速になります。ただし頻繁にINSERT/UPDATEが発生する場合は索引のオーバーヘッドも考慮してください。

実務でよくある改行コード処理パターン

CSV取込データのクレンジング

-- 外部CSVから取り込んだデータの改行コードを一括削除
UPDATE import_data
SET item_name = REPLACE(REPLACE(item_name, CHR(13), ''), CHR(10), ''),
    description = REPLACE(REPLACE(description, CHR(13), ''), CHR(10), ' ')
WHERE INSTR(item_name, CHR(10))       > 0
   OR INSTR(item_name, CHR(13))       > 0
   OR INSTR(description, CHR(10))     > 0
   OR INSTR(description, CHR(13))     > 0;
COMMIT;

改行コードを含む行だけをエクスポートして確認する

-- 改行コードを可視化してSELECT(確認用)
SELECT id,
       REPLACE(REPLACE(col_name, CHR(13), '[CR]'), CHR(10), '[LF]') AS visible
FROM your_table
WHERE INSTR(col_name, CHR(10)) > 0 OR INSTR(col_name, CHR(13)) > 0;

改行コードをHTMLのタグに変換する(表示用)

-- UPDATE しないで SELECT で変換(HTML表示用)
SELECT id,
       REPLACE(REPLACE(col_name, CHR(13)||CHR(10), '<br>'), CHR(10), '<br>') AS html_formatted
FROM your_table;

よくあるトラブルと解決法

ケース1:REPLACE後もまだ改行コードが残る

-- 原因: CRLF(13+10)のみ削除したが単独のLF/CRが残っている
-- または全角改行コード(CHR(13330)など)が混在している

-- 確認: DUMP で実際のコードを確認
SELECT DUMP(col_name) FROM your_table WHERE id = 1;

-- 解決: CRLFを先に削除してから単独CR/LFを削除
SELECT REPLACE(REPLACE(REPLACE(col_name,
    CHR(13)||CHR(10), ''),  -- CRLF を先に削除
    CHR(13), ''),           -- 単独CR を削除
    CHR(10), ''             -- 単独LF を削除
) AS cleaned
FROM your_table;

ケース2:REGEXP_REPLACE で ORA-22835 が発生する(CLOB)

-- ORA-22835: Buffer too small for CLOB to CHAR conversion
-- 原因: CLOBのサイズが内部バッファ(32767バイト)を超えている
-- 解決: REPLACE関数に切り替えるか、DBMS_LOBを使う

-- DBMS_LOB.REPLACE(大容量CLOB向け)
DECLARE
    v_clob CLOB;
BEGIN
    SELECT clob_col INTO v_clob FROM your_table WHERE id = 1 FOR UPDATE;
    v_clob := REPLACE(REPLACE(v_clob, CHR(13), ''), CHR(10), '');
    UPDATE your_table SET clob_col = v_clob WHERE id = 1;
    COMMIT;
END;
/

ケース3:WHERE条件なしでUPDATEしてしまった

-- COMMITしていなければROLLBACKで戻せる
ROLLBACK;

-- COMMITしてしまった場合: フラッシュバック(設定されている場合)
SELECT * FROM your_table AS OF TIMESTAMP TO_TIMESTAMP('2026-03-18 12:00:00', 'YYYY-MM-DD HH24:MI:SS')
WHERE id = 1;

ケース4:NULLカラムに REPLACE を適用するとエラーになる

-- REPLACEはNULLを含む値に適用するとNULLを返す(エラーではない)
-- NULL カラムに対して REPLACE を適用した場合の確認
SELECT REPLACE(NULL, CHR(10), '') FROM DUAL;
-- 結果: NULL(エラーにはならないがNULLのまま)

-- 必要に応じてNVL/NULLIFで対処
SELECT REPLACE(NVL(col_name, ''), CHR(10), '') AS cleaned
FROM your_table;

よくある質問

CHR(10) と CHR(13) どちらを先に削除すべきか?
厳密には「CRLFを先に削除→単独CR→単独LF」の順が推奨です。REPLACE(REPLACE(str, CHR(13)||CHR(10), ”), CHR(13), ”)のようにCRLFを一度に消してから残りを消すと、CRLF→CR+空文字→LF残りのような中途半端な状態を防げます。ただし多くの場合は順番に関係なく結果は同じです。
SELECT の REPLACE と UPDATE の REPLACE は同じ構文ですか?
はい、同じ構文です。SELECT で REPLACE を書いて結果を確認し、問題なければその REPLACE 式をそのまま UPDATE の SET 句に使えます。必ず SELECT で確認してから UPDATE するのが安全な手順です。
改行コードを削除したら文字が詰まって読めなくなった
空文字(”)への置換ではなく、スペース(’ ‘)やカンマ(’,’)など区切り文字に置換しましょう。REPLACE(col, CHR(10), ‘ ‘) とすると単語間にスペースが入り可読性が保てます。
NCLOB や NVARCHAR2 にも同じ方法が使えますか?
はい、NVARCHAR2 には REPLACE/REGEXP_REPLACE が使えます。NCLOB は CLOB と同様の注意点(32767バイト制限)があります。Nプレフィックス型は Unicode(UTF-16)格納のため、CHR() の引数はUnicodeコードポイントになりますが、改行コード CHR(10)/CHR(13) は同じ値で機能します。
定期的に新規データの改行コードを自動で削除したい
INSERT 時に BEFORE INSERT トリガーを使う方法が有効です。または アプリケーション側でデータを挿入する前にトリム処理を入れる方法が根本解決になります。DB側でのトリガー例::NEW.col := REPLACE(REPLACE(:NEW.col, CHR(13), ''), CHR(10), '');

まとめ

やりたいこと SQL 注意点
改行コードを含む行を検索 WHERE INSTR(col, CHR(10)) > 0 CR/LF両方を確認
改行コードの種類を確認 DUMP(col) ASCIIコード10=LF, 13=CR
削除(REPLACE) REPLACE(REPLACE(col, CHR(13), ''), CHR(10), '') CRLF→CR→LFの順に削除が安全
削除(REGEXP_REPLACE) REGEXP_REPLACE(col, '[\r\n]+', '') CLOBの32767制限に注意
スペースに置換 REPLACE(col, CHR(10), ' ') 文字が詰まるのを防ぐ
先頭・末尾だけ削除 LTRIM/RTRIM(col, CHR(10)||CHR(13)) 内部の改行は残る
UPDATEで削除 WHERE条件付きで REPLACE を適用 SELECT確認→UPDATE→COMMIT
大量CLOBの更新 PL/SQLで分割COMMIT ORA-01555対策
安全な実行の黄金ルール
1. DUMP関数で改行コードの種類を確認する
2. SELECT + REPLACE で更新後の値をプレビューする
3. WHERE句で対象行を絞り込んでからUPDATEする
4. COMMIT前にSELECTで確認し、問題なければCOMMITする

あわせて読みたい