SQLのTRIM関数は「文字列の前後から文字を取り除く」関数ですが、使いこなせている人は少ないです。基本の空白除去だけでなく、LEADING・TRAILING・BOTHで方向を指定した特定文字の削除、PostgreSQLのBTRIM(複数文字を一括削除)、関数インデックスによるパフォーマンス対策、CSVインポートデータの整形や引用符除去など実務パターンまで本記事で網羅します。
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 |
基本の使い方:空白除去
引数に文字列またはカラム名を渡すだけで、両端の半角スペースが除去されます。
-- 両端の半角スペースを除去
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('Hello World') → 'Hello World'(中間スペースはそのまま)。中間も含めてすべて削除したい場合は REPLACE(col, ' ', '') を使ってください。詳しくはSQLでスペースを削除する方法を参照。LEADING / TRAILING / BOTH:指定文字を方向別に削除する
TRIM関数の真価は「方向を指定して特定の文字を削除できる」点にあります。SQL標準のフル構文は TRIM([LEADING|TRAILING|BOTH] [文字] FROM 文字列) です。
-- 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の動作ルール
指定した文字列(1文字または複数文字)を先頭・末尾から連続する限り繰り返し除去します。「連続していない」場所より内側には入りません。
TRIM(BOTH 'x' FROM 'xxHxello xx') → 'Hxello '(内側のxとスペースは残る)-- 連続する先頭・末尾の 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: 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: 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: 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 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(文字集合) | × | ○(独自) | × | × |
LTRIM(RTRIM(col)) で代替してください。特定文字の除去はREPLACEを組み合わせます。PostgreSQL独自: BTRIM で複数文字を一括削除する
BTRIM(文字列, 文字集合) は、第2引数に指定した文字の集合に含まれる任意の文字を両端から連続して除去します。順序は関係なく「集合のいずれか」が対象になります。
-- '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'
制御文字(タブ・改行)の除去
TRIMはデフォルトで半角スペース(U+0020)のみを対象とします。タブ(CHR(9))・改行(CHR(10))・復帰(CHR(13))はREPLACEでそれぞれ削除してください。
-- タブ(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: 空白類(スペース・タブ・改行)を正規表現で両端から除去 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: データを事前にクリーニングする(最善)
-- 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)を作成する
-- 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 + 余白を含む検索(簡易的)
-- データ件数が少なく、インデックス不要な場合 SELECT * FROM customers WHERE name LIKE '%田中 太郎%'; -- または: TRIM結果と直接比較せず余裕を持たせた比較 SELECT * FROM customers WHERE TRIM(name) LIKE '%田中%'; -- 完全一致でなくとも検索できる
実務でよく使うTRIMパターン集
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時に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 | 正規表現 |
-- 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;
よくある質問
TRIM('x' FROM str) はBOTHを省略した書き方で、TRIM(BOTH 'x' FROM str) と同等です。ただし省略形はSQL標準外の場合があるため、移植性を重視するなら明示的にBOTHを書く方が安全です。BTRIM(str, 'abc')なら ‘a’・’b’・’c’ の集合を確実に除去できます。OracleではLTRIM(RTRIM(str, 'abc'), 'abc')で同様の結果が得られます。TRIM('x' FROM str) が使えます。それ以前のバージョンでは REPLACE で代替するか、計算列 + インデックスを活用してください。空白のみなら全バージョンで LTRIM(RTRIM(col)) が使えます。NULLIF(TRIM(col), '') を使います。NULLIF(A, B) は A = B のときNULLを返す関数で、TRIM後が空文字の場合にNULLへ変換できます。例: SELECT NULLIF(TRIM(name), '') AS name FROM customers;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に変換
関連記事:SQLでスペース(空白)を削除する方法(REPLACE・全角スペース・UPDATEパターン)、REPLACE関数で文字列を置換する方法、LENGTH関数で文字列の長さを取得する方法