【序文】
SQLServer2017 で追加された TRIM関数。
全角空白(任意の一文字)の削除にも対応している。
1> SELECT TRIM(N' ' FROM N' 令和元年');
2> GO
------
令和元年
(1 行処理されました)
少々違和感のある文法だけど。
しかしこの手の組み込みトリミング関数は半角空白にしか対応してない場合が多い。SQLServer で言えば、LTRIM
、RTRIM
関数とか。
全角空白にも対応させる必要に迫られ関数を自作する局面も多いが、難しい処理ではない。
特に簡単な方法を取り上げる。
【環境】
SQLServer | SQLCMD | SSMS |
---|---|---|
2017 | 14.0.1000.169 | v18.2 |
設定はデフォルト。 | ||
従って文字列の比較で半角・全角空白は区別されない。 |
【PATINDEX関数を利用する方法】
PATINDEX関数を利用すれば、半角・全角空白以外の文字が最初に現れる先頭位置を求めることができる。
後はその文字数分削除すれば良い。
ループで回し、先頭から一文字ずつ自力で調べて……といった冗長な実装を見かけることがあるが、そんな面倒なことをする必要はない。
実装例は以下。
DECLARE @str NVARCHAR(MAX) = N' 令和元年'; -- 対象文字列(先頭に半角・全角空白)
DECLARE @cutLen INT = PATINDEX(N'%[^ ]%', @str) - 1; -- カットする先頭文字列数
SELECT
@str [処理対象文字列]
, @cutLen [カットする先頭文字列数]
, RIGHT(@str, LEN(@str) - @cutLen) [処理後文字列(RIGHT版)]
, STUFF(@str, 1, @cutLen, N'') [処理後文字列(STUFF版)]
;
N' 令和元年'
は
+
+
+令和元年
と半角・全角空白が先頭に含まれる。
N'%[^ ]%'
は ^
+
で半角・全角空白以外の意味。
トリミング処理は RIGHT
STUFF
関数のどちらでも良い。
パフォーマンスの差は未検証だが、誤差の範囲だろう。お好きな方を。
勿論、先頭に半角・全角空白が含まれないケースでもこのコードは正しく動作する。
また半角・全角空白が区別される環境でも、N'%[^ ]%'
に全角空白を追記し、N'%[^ ]%'
とすれば良い。
半角・全角が区別される環境については別投稿にまとめたのでそちら参照。
【自力で空白を調べるアルゴリズム】
関数化すれば以下の処理だけ書けば良い。トリミング対象文字列は引数で与えられるものとする。
1. 引数で与えられた文字列の先頭 1文字が空白以外の場合は処理を終了
2. 引数で与えられた文字列の先頭 1文字を削除し、それを引数に自分自身をコール
実装例は以下。
IF OBJECT_ID (N'dbo.LTrimEX', N'FN') IS NOT NULL
DROP FUNCTION LTrimEX;
GO
-- 全角空白対応版 LTRIM
CREATE FUNCTION dbo.LTrimEX(@STR NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
IF LEFT(@STR, 1) = N' ' -- 先頭1文字が空白の場合
SELECT @STR = dbo.LTrimEX(STUFF(@STR, 1, 1, N'')); -- 先頭1文字を削除し再帰呼び出し
RETURN(@STR);
END;
GO
実行例は以下。
1> PRINT dbo.LTrimEX(N' 令和元年');
2> GO
令和元年
関数の中身はたった 3行。
簡単なアルゴリズムなので大抵のプログラミング言語にも移植できるだろう。