【SQL】TRIM関数完全ガイド|空白・指定文字の削除・LEADING/TRAILING/BOTH・BTRIM・実務パターンまで解説

SQLのTRIM関数は「文字列の前後から文字を取り除く」関数ですが、使いこなせている人は少ないです。基本の空白除去だけでなく、LEADING・TRAILING・BOTHで方向を指定した特定文字の削除、PostgreSQLのBTRIM(複数文字を一括削除)、関数インデックスによるパフォーマンス対策、CSVインポートデータの整形や引用符除去など実務パターンまで本記事で網羅します。

この記事で学べること:TRIM関数の完全構文(LEADING/TRAILING/BOTH)・指定文字削除・LTRIM/RTRIM・PostgreSQL独自のBTRIM・制御文字(タブ・改行)除去・WHERE句でのTRIM使用時の注意点と関数インデックス・実務クリーニングパターン集
スポンサーリンク

TRIM関数とは

TRIM関数はSQL標準(ISO/IEC 9075)で定義された文字列関数です。文字列の先頭・末尾・両端から指定した文字を取り除きます。引数を省略すると半角スペース(U+0020)を除去します。

構文 除去位置 除去文字 対応DBMS
TRIM(str) 両端 半角スペース 全DB
TRIM(BOTH x FROM str) 両端 指定文字x 全DB
TRIM(LEADING x FROM str) 先頭のみ 指定文字x 全DB
TRIM(TRAILING x FROM str) 末尾のみ 指定文字x 全DB
LTRIM(str) 先頭のみ 半角スペース 全DB
RTRIM(str) 末尾のみ 半角スペース 全DB
BTRIM(str, chars) 両端 複数文字(集合) PostgreSQL

基本の使い方:空白除去

引数に文字列またはカラム名を渡すだけで、両端の半角スペースが除去されます。

TRIM基本(空白除去)
-- 両端の半角スペースを除去
SELECT TRIM('  Hello World  ') AS result;
-- 結果: 'Hello World'  ※中間のスペースは残る

-- カラムに適用
SELECT TRIM(name) AS trimmed_name FROM customers;

-- LTRIM: 先頭(左)のみ
SELECT LTRIM('  Hello  ') AS result;  -- 'Hello  '

-- RTRIM: 末尾(右)のみ
SELECT RTRIM('  Hello  ') AS result;  -- '  Hello'

-- LTRIM + RTRIM の組み合わせ(TRIM相当・古いSQL Server対応)
SELECT LTRIM(RTRIM('  Hello  ')) AS result;  -- 'Hello'
TRIM は前後のみ。中間スペースは除去しない
TRIM('Hello World')'Hello World'(中間スペースはそのまま)。中間も含めてすべて削除したい場合は REPLACE(col, ' ', '') を使ってください。詳しくはSQLでスペースを削除する方法を参照。

LEADING / TRAILING / BOTH:指定文字を方向別に削除する

TRIM関数の真価は「方向を指定して特定の文字を削除できる」点にあります。SQL標準のフル構文は TRIM([LEADING|TRAILING|BOTH] [文字] FROM 文字列) です。

LEADING / TRAILING / BOTH の基本
-- LEADING: 先頭から指定文字を除去
SELECT TRIM(LEADING 'x' FROM 'xxHello Worldxx');
-- 結果: 'Hello Worldxx'

-- TRAILING: 末尾から指定文字を除去
SELECT TRIM(TRAILING 'x' FROM 'xxHello Worldxx');
-- 結果: 'xxHello World'

-- BOTH: 両端から指定文字を除去(デフォルト)
SELECT TRIM(BOTH 'x' FROM 'xxHello Worldxx');
-- 結果: 'Hello World'

-- 文字を省略した場合: スペースが対象(以下は等価)
SELECT TRIM('  Hello  ');
SELECT TRIM(BOTH ' ' FROM '  Hello  ');
SELECT TRIM(BOTH FROM '  Hello  ');

文字指定TRIMの動作ルール

重要:TRIM([LEADING|TRAILING|BOTH] ‘x’ FROM str) の除去ルール
指定した文字列(1文字または複数文字)を先頭・末尾から連続する限り繰り返し除去します。「連続していない」場所より内側には入りません。
TRIM(BOTH 'x' FROM 'xxHxello xx')'Hxello '(内側のxとスペースは残る)
TRIM指定文字の動作確認
-- 連続する先頭・末尾の x をすべて除去
SELECT TRIM(BOTH 'x' FROM 'xxxABCxxx');   -- 'ABC'
SELECT TRIM(BOTH 'x' FROM 'xxxABCxXxx'); -- 'ABCxX'  ← 大文字Xは別文字

-- 複数文字を指定しても「その文字列パターン」ではなく
-- 「その文字を1文字ずつ」除去(DBMSによって動作が異なる注意点)
-- MySQL / Oracle: 1文字ずつ評価
SELECT TRIM(BOTH 'ab' FROM 'ababHelloabab');
-- MySQL:  'Hello'(a または b を個別に除去)
-- Oracle: 'Hello'(同様)

-- スペース以外のいろんな文字を除去する例
SELECT TRIM(LEADING '0' FROM '000123');   -- '123'(ゼロパディング除去)
SELECT TRIM(TRAILING '/' FROM 'path/');   -- 'path'(末尾スラッシュ除去)
SELECT TRIM(BOTH '"' FROM '"Hello"');     -- 'Hello'(引用符除去)
実務でよく使うパターン:ゼロパディング除去(TRIM(LEADING '0' FROM code))、末尾スラッシュ除去(TRIM(TRAILING '/' FROM path))、引用符除去(TRIM(BOTH '"' FROM field)

DBMS別の構文とサポート状況

MySQL
-- MySQL: TRIM / LTRIM / RTRIM すべて対応
SELECT TRIM('  Hello  ');                           -- 'Hello'
SELECT TRIM(LEADING '0' FROM '00123');              -- '123'
SELECT TRIM(TRAILING '.' FROM 'price.');            -- 'price'
SELECT TRIM(BOTH '#' FROM '##tag##');               -- 'tag'

-- LTRIM / RTRIM: 半角スペースのみ(文字指定不可)
SELECT LTRIM('   Hello');                           -- 'Hello'
SELECT RTRIM('Hello   ');                           -- 'Hello'
PostgreSQL
-- PostgreSQL: TRIM / LTRIM / RTRIM + 独自の BTRIM
SELECT TRIM('  Hello  ');                           -- 'Hello'
SELECT TRIM(LEADING FROM '  Hello  ');              -- 'Hello  '
SELECT TRIM(TRAILING FROM '  Hello  ');             -- '  Hello'

-- PostgreSQL独自: LTRIM / RTRIM に削除文字集合を指定可能
SELECT LTRIM('xxHello', 'x');                       -- 'Hello'  ← 文字指定OK
SELECT RTRIM('Helloyy', 'y');                       -- 'Hello'

-- BTRIM: 両端から文字「集合」に含まれる文字を削除
SELECT BTRIM('xyzHellozyx', 'xyz');                 -- 'Hello'
-- 'x','y','z' のどれかに該当する文字を両端から除去

-- PostgreSQL TRIM BOTH は標準構文で使える
SELECT TRIM(BOTH 'x' FROM 'xxxHelloxxx');           -- 'Hello'
Oracle
-- Oracle: TRIM / LTRIM / RTRIM 対応(LEADING/TRAILING/BOTH指定可)
SELECT TRIM('  Hello  ') FROM dual;                 -- 'Hello'
SELECT TRIM(LEADING ' ' FROM '  Hello  ') FROM dual; -- 'Hello  '
SELECT TRIM(TRAILING ' ' FROM '  Hello  ') FROM dual;-- '  Hello'

-- Oracle の LTRIM / RTRIM は文字集合を指定できる(PostgreSQLと同様)
SELECT LTRIM('xxHello', 'x') FROM dual;             -- 'Hello'
SELECT RTRIM('Hello##', '#') FROM dual;             -- 'Hello'

-- 複数文字の集合(順不同で両端から除去)
SELECT LTRIM('xyzHello', 'xyz') FROM dual;          -- 'Hello'
SQL Server
-- SQL Server 2017以降: TRIM 関数が追加された
SELECT TRIM('  Hello  ');                           -- 'Hello'(SQL Server 2017+)

-- SQL Server 2017+: TRIM に除去文字を指定可能(拡張構文)
SELECT TRIM('0' FROM '0001234');                    -- '1234'(SQL Server 2022+)

-- SQL Server 2016以前: LTRIM / RTRIM で代替
SELECT LTRIM(RTRIM('  Hello  '));                   -- 'Hello'

-- LTRIM / RTRIM: SQL Serverは文字指定不可(スペースのみ)
機能 MySQL PostgreSQL Oracle SQL Server
TRIM(スペース除去) ○(2017+)
TRIM LEADING/TRAILING/BOTH △(2022+で文字指定)
LTRIM / RTRIM(スペース) ○(全バージョン)
LTRIM/RTRIM + 文字指定 × ×
BTRIM(文字集合) × ○(独自) × ×
SQL Server 2016以前の対策:TRIM関数が存在しないため LTRIM(RTRIM(col)) で代替してください。特定文字の除去はREPLACEを組み合わせます。

PostgreSQL独自: BTRIM で複数文字を一括削除する

BTRIM(文字列, 文字集合) は、第2引数に指定した文字の集合に含まれる任意の文字を両端から連続して除去します。順序は関係なく「集合のいずれか」が対象になります。

BTRIMの動作(PostgreSQL)
-- 'x', 'y', 'z' のいずれかを両端から除去
SELECT BTRIM('xyzHellozyx', 'xyz');   -- 'Hello'
SELECT BTRIM('zzzHello', 'xyz');      -- 'Hello'  z を除去
SELECT BTRIM('zyxHello', 'xyz');      -- 'Hello'  順序無関係

-- 数字を両端から除去
SELECT BTRIM('123Hello456', '0123456789');  -- 'Hello'

-- スペースと特定記号を同時に除去
SELECT BTRIM('  ##tag##  ', ' #');    -- 'tag'  スペースと#を両端から除去

-- LTRIM / RTRIM でも文字指定可能(PostgreSQL・Oracle)
SELECT LTRIM('###Hello', '#');        -- 'Hello'
SELECT RTRIM('Hello###', '#');        -- 'Hello'
BTRIMはTRIM BOTH との違い:TRIM(BOTH ‘xyz’ FROM str) は ‘xyz’ という3文字の文字列パターンを除去しようとします(DB依存)。BTRIMは ‘x’・’y’・’z’ を個別の文字の集合として扱い、どれかに当てはまれば除去します。複数種類の文字を除去したいならBTRIM(またはLTRIM/RTRIMに文字集合指定)が確実です。

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

TRIMはデフォルトで半角スペース(U+0020)のみを対象とします。タブ(CHR(9))・改行(CHR(10))・復帰(CHR(13))はREPLACEでそれぞれ削除してください。

タブ・改行の除去(全DBMS)
-- タブ(CHR(9))を削除
SELECT REPLACE(col, CHR(9), '') FROM table;

-- 改行LF(CHR(10))を削除
SELECT REPLACE(col, CHR(10), '') FROM table;

-- 改行CR(CHR(13))を削除(Windows改行対策)
SELECT REPLACE(col, CHR(13), '') FROM table;

-- スペース・タブ・改行をまとめて削除
SELECT REPLACE(REPLACE(REPLACE(TRIM(col), CHR(9), ''), CHR(10), ''), CHR(13), '')
FROM table;

-- MySQL では CHAR() 関数を使う(CHR()ではない)
SELECT REPLACE(col, CHAR(10), '') FROM table;   -- MySQL

-- SQL Server では CHAR() を使う
SELECT REPLACE(col, CHAR(13) + CHAR(10), '') FROM table;  -- SQL Server CRLF
PostgreSQL: REGEXP_REPLACEで制御文字を一括除去
-- PostgreSQL: 空白類(スペース・タブ・改行)を正規表現で両端から除去
SELECT REGEXP_REPLACE(col, '^[\s]+|[\s]+$', '', 'g') FROM table;

-- または: 制御文字を空文字に置換
SELECT REGEXP_REPLACE(col, '[\x00-\x1F]', '', 'g') FROM table;

WHERE句でTRIMを使う場合のパフォーマンス注意点

検索条件に TRIM(col) = '値' と書くとインデックスが使われません。大量データのテーブルでは全件スキャンになり性能問題が発生します。

インデックスが使われないパターン(非推奨)
-- NG: col にインデックスがあっても使われない
SELECT * FROM customers WHERE TRIM(name) = '田中 太郎';
SELECT * FROM products  WHERE LTRIM(RTRIM(code)) = 'P001';

対策1: データを事前にクリーニングする(最善)

UPDATEで事前クリーニング(根本解決)
-- STEP1: 対象行を確認
SELECT COUNT(*) FROM customers WHERE name != TRIM(name);

-- STEP2: 差分を目視確認
SELECT name, TRIM(name) AS cleaned FROM customers WHERE name != TRIM(name);

-- STEP3: UPDATE でデータを修正
UPDATE customers
SET    name = TRIM(name)
WHERE  name != TRIM(name);

-- STEP4: 以後はアプリ側でTRIMしてからINSERT/UPDATEする

対策2: 関数インデックス(Function-Based Index)を作成する

関数インデックスでTRIM検索を高速化
-- Oracle: 関数ベースインデックス
CREATE INDEX idx_trim_name ON customers (TRIM(name));
-- → WHERE TRIM(name) = '田中' でインデックスが使われる

-- PostgreSQL: 式インデックス
CREATE INDEX idx_trim_name ON customers ((TRIM(name)));
-- → WHERE TRIM(name) = '田中' でインデックスが使われる

-- MySQL 8.0+: 関数インデックス
CREATE INDEX idx_trim_name ON customers ((TRIM(name)));
-- → WHERE TRIM(name) = '田中' でインデックスが使われる(8.0.13+)

-- SQL Server: 計算列 + インデックスで代替
ALTER TABLE customers ADD name_trimmed AS LTRIM(RTRIM(name));
CREATE INDEX idx_name_trimmed ON customers (name_trimmed);

対策3: LIKE + 余白を含む検索(簡易的)

LIKEで両端スペースを許容した検索(小規模向け)
-- データ件数が少なく、インデックス不要な場合
SELECT * FROM customers WHERE name LIKE '%田中 太郎%';

-- または: TRIM結果と直接比較せず余裕を持たせた比較
SELECT * FROM customers
WHERE  TRIM(name) LIKE '%田中%';  -- 完全一致でなくとも検索できる

実務でよく使うTRIMパターン集

CSVインポート後のデータクリーニング

CSVをインポートすると、値の前後に余計なスペースやダブルクォートが混入することがあります。

CSVインポート後のクリーニング
-- 一時テーブルにインポート後、クリーニングして本番テーブルへ
INSERT INTO products (code, name, price)
SELECT
    TRIM(code),
    TRIM(name),
    CAST(TRIM(price) AS DECIMAL(10,2))
FROM   import_staging
WHERE  TRIM(code) <> '';   -- 空行を除外

-- ダブルクォートも除去する場合
SELECT
    TRIM(BOTH '"' FROM TRIM(code))  AS code,
    TRIM(BOTH '"' FROM TRIM(name))  AS name
FROM import_staging;

電話番号・郵便番号の正規化

電話番号・郵便番号の正規化
-- 郵便番号からハイフンとスペースを除去
SELECT REPLACE(REPLACE(TRIM(zip_code), '-', ''), ' ', '') AS normalized_zip
FROM customers;

-- 電話番号の括弧・ハイフン・スペースを除去して数字のみに
SELECT REPLACE(REPLACE(REPLACE(REPLACE(TRIM(phone), '-', ''), ' ', ''), '(', ''), ')', '')
AS digits_only_phone
FROM customers;

コードのゼロパディング除去・整形

ゼロパディングの除去・コード整形
-- 先頭のゼロを除去(コード正規化)
SELECT TRIM(LEADING '0' FROM '000123')  AS code;  -- '123'

-- ただし TRIM(LEADING '0' FROM '0') は '' になるので注意
SELECT TRIM(LEADING '0' FROM '0');  -- '' (空文字)
-- 必要なら NULLIF + COALESCE で保護
SELECT COALESCE(NULLIF(TRIM(LEADING '0' FROM code), ''), '0') AS code
FROM table;

-- 末尾のゼロを除去(小数の整形)
SELECT TRIM(TRAILING '0' FROM '1.5000')  AS price;   -- '1.5'
SELECT TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM '100.000')) AS price;  -- '100'

APIレスポンスや入力値のサニタイズ

外部データの入力クリーニング(INSERTトリガー代替)
-- アプリからのINSERT時にSQL側でもTRIMをかける(二重保護)
INSERT INTO messages (user_id, body, created_at)
VALUES (
    1,
    TRIM(:input_body),   -- バインドパラメータの前後空白を除去
    NOW()
);

-- SELECT時にクリーニングしてビューで提供
CREATE VIEW v_clean_customers AS
SELECT
    id,
    TRIM(name)          AS name,
    TRIM(email)         AS email,
    TRIM(address)       AS address
FROM customers;

TRIMを使った重複チェック

スペース違いの重複を検出する
-- 同一人物が「田中」「 田中 」「田中 」として登録されている重複を検出
SELECT
    TRIM(name)        AS normalized_name,
    COUNT(*)          AS cnt,
    GROUP_CONCAT(id)  AS ids        -- MySQL
FROM customers
GROUP BY TRIM(name)
HAVING COUNT(*) > 1
ORDER BY cnt DESC;

REGEXP_REPLACEとの使い分け

TRIMで対応できない複雑なパターン(複数種類の記号・Unicode空白・前後の数字など)は正規表現関数を使います。

ユースケース 推奨関数 理由
両端のスペース除去 TRIM 標準・全DB・高速
片側スペース除去 LTRIM / RTRIM シンプル・全DB
1種類の文字を両端から除去 TRIM BOTH ‘x’ FROM 標準SQL
複数種類の文字を両端から除去 BTRIM(PgSQL)/ LTRIM+RTRIM(Oracle) 集合として処理
中間スペースも含めて全削除 REPLACE 位置不問
タブ・改行・制御文字除去 REPLACE + CHR()/CHAR() 文字コード指定
複雑なパターン(Unicode・複数条件) REGEXP_REPLACE 正規表現
REGEXP_REPLACEが必要なケース
-- PostgreSQL: 全種類の空白類(スペース・タブ・改行・全角)を両端から除去
SELECT REGEXP_REPLACE(col, '^[\s\u3000]+|[\s\u3000]+$', '', 'g')
FROM table;

-- Oracle: REGEXP_REPLACE で先頭末尾の空白類を除去
SELECT REGEXP_REPLACE(col, '^[[:space:]]+|[[:space:]]+$', '')
FROM table;

-- MySQL 8.0+: REGEXP_REPLACE で先頭末尾のスペース類を除去
SELECT REGEXP_REPLACE(col, '^[[:space:]]+|[[:space:]]+$', '')
FROM table;

よくある質問

QTRIM(‘x’ FROM str) とTRIM(BOTH ‘x’ FROM str) は同じですか?
Aはい、TRIM('x' FROM str) はBOTHを省略した書き方で、TRIM(BOTH 'x' FROM str) と同等です。ただし省略形はSQL標準外の場合があるため、移植性を重視するなら明示的にBOTHを書く方が安全です。
QTRIM関数で複数種類の文字を同時に除去できますか?
ATRIM BOTH で複数文字文字列を指定した場合の動作はDBMSによって異なります。PostgreSQLのBTRIM(str, 'abc')なら ‘a’・’b’・’c’ の集合を確実に除去できます。OracleではLTRIM(RTRIM(str, 'abc'), 'abc')で同様の結果が得られます。
QSQL Serverで特定文字をTRIMするには?
ASQL Server 2022以降は TRIM('x' FROM str) が使えます。それ以前のバージョンでは REPLACE で代替するか、計算列 + インデックスを活用してください。空白のみなら全バージョンで LTRIM(RTRIM(col)) が使えます。
QWHERE TRIM(col) = ‘値’ でインデックスが使われない問題を解決するには?
A①データを事前にUPDATEでクリーニングしてインデックスをそのまま使う(最善)、②TRIM(col)に関数インデックス(Oracle・PostgreSQL・MySQL 8.0+)を作成する、③の三択です。小規模テーブルなら全件スキャンでも問題ない場合があります。
QTRIM後に空文字になった場合をNULLに変換するには?
ANULLIF(TRIM(col), '') を使います。NULLIF(A, B) は A = B のときNULLを返す関数で、TRIM後が空文字の場合にNULLへ変換できます。例: SELECT NULLIF(TRIM(name), '') AS name FROM customers;
Q全角スペースも除去したい場合はどうすればよいですか?
ATRIMは半角スペース(U+0020)のみを対象とします。全角スペース(U+3000)は REPLACE(col, ' ', '')REPLACE(col, CHR(12288), '')(Oracle)で除去してください。半角・全角を両方対処するには REPLACE(REPLACE(TRIM(col), ' ', ''), ' ', '') とネストします。詳しくはSQLでスペースを削除する方法を参照。

まとめ

SQLのTRIM関数は基本の空白除去にとどまらず、LEADING/TRAILING/BOTHで方向を制御しながらあらゆる文字を削除できる多機能な関数です。ポイントをまとめます。

  • TRIM(str):両端の半角スペースを除去。全DBで使える最も基本的な形
  • TRIM(LEADING/TRAILING/BOTH ‘x’ FROM str):方向を指定して特定文字を除去。ゼロパディング・引用符・スラッシュの除去に最適
  • LTRIM / RTRIM:片側のスペース除去。Oracle・PostgreSQLでは文字集合も指定可能
  • BTRIM(str, chars)(PostgreSQL独自):複数種類の文字を集合として両端から一括除去
  • 制御文字除去:タブ・改行はREPLACE + CHR()/CHAR()で対応
  • パフォーマンス:WHERE TRIM(col) = ‘値’ はインデックスが効かない。事前クリーニングか関数インデックスで対策
  • TRIM後の空文字対策NULLIF(TRIM(col), '') でNULLに変換
使い分けのポイント:空白除去なら TRIM、特定文字除去なら TRIM BOTH ‘x’ FROM、複数種類の文字除去(PostgreSQL)なら BTRIM、全角スペース・中間スペースは REPLACE、複雑なパターンは REGEXP_REPLACE を使いましょう。

関連記事:SQLでスペース(空白)を削除する方法(REPLACE・全角スペース・UPDATEパターン)REPLACE関数で文字列を置換する方法LENGTH関数で文字列の長さを取得する方法