Ccmmutty logo
Commutty IT
0 pv9 min read

【SQL Server】LEN関数に隠された「RTRIM機能」

https://cdn.magicode.io/media/notebox/433cc814-ac38-4aff-ab51-78f8ea91e21a.jpeg

SQL ServerのLEN関数に隠された「RTRIM機能」

最近はORMを使うことが多く、SQL関数を直接書く機会は減っているかもしれません。
しかし、ストアドプロシージャやビュー、複雑なクエリを書く際には、
SQL Serverの関数の特性を理解しておくことが重要です。
今回は久々にT-SQLを触った際に知ったLEN関数の仕様についてメモを残します。

LEN関数の基本仕様

構文

LEN ( string_expression )

公式ドキュメントの重要な注記

Microsoft公式ドキュメントには、以下のように記載されています:
LEN関数は、末尾の空白を除外します。
つまり、LEN関数は文字列の右側(末尾)にある空白文字をカウントしないのです。
コメントが無かったりするとこれがたまにバグ検知に引っ掛かります。

実際に検証してみる

テストデータの準備

まずは検証用のテストテーブルとデータを用意しましょう。
-- ========================================
-- SQL1: テストデータの準備
-- ========================================
CREATE TABLE StringTest (
    ID INT PRIMARY KEY,
    TestString NVARCHAR(50),
    Description NVARCHAR(100)
);

INSERT INTO StringTest (ID, TestString, Description) VALUES
(1, 'Hello', '通常の文字列'),
(2, 'Hello     ', '右側に5つの半角スペース'),
(3, '     Hello', '左側に5つの半角スペース'),
(4, '  Hello  ', '両側に半角スペース'),
(5, 'Hello   ', '右側に3つの全角スペース'),
(6, '', '空文字列'),
(7, '     ', '半角スペースのみ5文字');

LEN関数の挙動確認

実際にLEN関数の挙動を確認してみます。
-- ========================================
-- SQL2: LEN関数の挙動確認
-- ========================================
SELECT 
    ID,
    TestString,
    '[' + TestString + ']' AS BracketedString,
    LEN(TestString) AS LEN_Result,
    DATALENGTH(TestString) AS DATALENGTH_Result,
    Description
FROM StringTest
ORDER BY ID;

実行結果

IDTestStringBracketedStringLEN_ResultDATALENGTH_ResultDescription
1Hello[Hello]510通常の文字列
2Hello[Hello ]520右側に5つの半角スペース
3Hello[ Hello]1020左側に5つの半角スペース
4Hello[ Hello ]718両側に半角スペース
5Hello[Hello   ]516右側に3つの全角スペース
6[]00空文字列
7[ ]010半角スペースのみ5文字

結果から分かること

LEN関数の挙動
  1. ID 2のケース: 右側の半角スペース5文字が無視され、LENは5を返す
  2. ID 3のケース: 左側のスペースはカウントされ、LENは10を返す(スペース5文字 + Hello5文字)
  3. ID 4のケース: 右側のスペースのみ無視され、LENは7を返す(左2文字 + Hello5文字)
  4. ID 5のケース: 全角スペースも末尾なら無視される(LENは5のまま)
  5. ID 7のケース: スペースのみの文字列では、全て末尾扱いとなりLENは0を返す
DATALENGTH関数の挙動
  1. ID 1のケース: 'Hello'(5文字)→ 10バイト(NVARCHAR型なので1文字=2バイト)
  2. ID 2のケース: 'Hello'(5文字)+ スペース5文字 = 10文字 → 20バイト
  3. ID 3のケース: スペース5文字 + 'Hello'(5文字)= 10文字 → 20バイト
  4. ID 4のケース: スペース2文字 + 'Hello'(5文字)+ スペース2文字 = 9文字 → 18バイト
  5. ID 5のケース: 'Hello'(5文字)+ 全角スペース3文字 = 8文字 → 16バイト
  6. ID 7のケース: スペース5文字 → 10バイト(LENは0だがDATALENGTHは10

DATALENGTH関数との違い

LEN関数と混同しやすいのがDATALENGTH関数です。

主な違い

関数末尾の空白戻り値の単位用途
LEN除外する文字数文字列の実質的な長さを取得
DATALENGTHカウントするバイト数データの実際のサイズを取得
重要なのはID 7のケース
  • LEN: 末尾スペースを全て除外するため、スペースのみの文字列は 0 を返す
  • DATALENGTH: 実際に格納されているデータのバイト数を返すため 10 を返す
この違いにより、空文字チェックバリデーションでは注意が必要
-- ❌ LENだけでは不十分
IF LEN(@UserInput) = 0
    PRINT '空です'  -- スペースのみの入力も「空」と判定されてしまう

-- ⭕ より厳密なチェック
IF LEN(LTRIM(RTRIM(@UserInput))) = 0
    PRINT '空またはスペースのみです'

-- ⭕ データが実際に存在するかチェック
IF DATALENGTH(@UserInput) = 0
    PRINT '完全に空です'
NVARCHAR型のバイト計算
DATALENGTHはバイト数を返すため、文字数を知りたい場合は以下の計算が必要です。
実際の文字数 = DATALENGTH(文字列) ÷ 2  -- NVARCHAR型の場合
例:
  • ID 2: DATALENGTH = 20バイト → 20 ÷ 2 = 10文字(実際の格納文字数)
  • ID 7: DATALENGTH = 10バイト → 10 ÷ 2 = 5文字(スペース5つ)

使い分けの例

-- ========================================
-- SQL3: LENとDATALENGTHの使い分け
-- ========================================
DECLARE @Text1 NVARCHAR(50) = 'Hello     ';  -- 右側に5つのスペース
DECLARE @Text2 NVARCHAR(50) = 'こんにちは';

SELECT 
    'Text1' AS TextName,
    @Text1 AS Value,
    LEN(@Text1) AS LEN_文字数,
    DATALENGTH(@Text1) AS DATALENGTH_バイト数,
    DATALENGTH(@Text1) / 2 AS 実際の文字数_NVARCHAR

UNION ALL

SELECT 
    'Text2' AS TextName,
    @Text2 AS Value,
    LEN(@Text2) AS LEN_文字数,
    DATALENGTH(@Text2) AS DATALENGTH_バイト数,
    DATALENGTH(@Text2) / 2 AS 実際の文字数_NVARCHAR;

実務での注意点

1. バリデーションチェックでの落とし穴

-- ❌ 期待通りに動作しない可能性
IF LEN(@InputString) = 0
    PRINT '空文字列です'

-- ⭕ スペースのみの文字列も検出したい場合
IF LEN(LTRIM(RTRIM(@InputString))) = 0
    PRINT '空文字列またはスペースのみです'

2. データクレンジングでの考慮

ユーザー入力データなどで、末尾にスペースが含まれている可能性がある場合
-- LENだけでは不十分な場合がある
SELECT LEN(UserInput) -- 末尾スペースは無視される

-- 実際のデータ長を確認したい場合
SELECT DATALENGTH(UserInput) / 2 -- NVARCHARの場合は2で割る

3. 空白のみの文字列の扱い

-- ========================================
-- SQL4: 空白のみの文字列の扱い
-- ========================================
DECLARE @OnlySpaces NVARCHAR(50) = '     ';  -- 半角スペース5文字

SELECT 
    '[' + @OnlySpaces + ']' AS 元の文字列,
    LEN(@OnlySpaces) AS LEN結果,
    DATALENGTH(@OnlySpaces) AS DATALENGTH結果,
    CASE 
        WHEN LEN(@OnlySpaces) = 0 THEN '空とみなされる'
        ELSE '空ではない'
    END AS LENでの判定,
    CASE 
        WHEN DATALENGTH(@OnlySpaces) = 0 THEN '空とみなされる'
        ELSE '空ではない'
    END AS DATALENGTHでの判定;
-- ========================================
-- SQL5: バリデーション例
-- ========================================
-- パターン1: 空文字列またはスペースのみをチェック
DECLARE @UserInput NVARCHAR(100) = '     ';

IF LEN(LTRIM(RTRIM(@UserInput))) = 0
    PRINT '入力が空です';
ELSE
    PRINT '有効な入力です: ' + @UserInput;


-- パターン2: 最小文字数チェック(空白を除いた実質的な長さ)
DECLARE @Username NVARCHAR(50) = 'User   ';

IF LEN(LTRIM(RTRIM(@Username))) < 3
    PRINT 'ユーザー名は3文字以上必要です';
ELSE
    PRINT 'ユーザー名OK: 実質文字数=' + CAST(LEN(LTRIM(RTRIM(@Username))) AS NVARCHAR);


-- パターン3: データの実サイズチェック
DECLARE @Description NVARCHAR(200) = 'This is a test     ';

SELECT 
    'Description' AS ColumnName,
    LEN(@Description) AS 表示文字数,
    DATALENGTH(@Description) / 2 AS 実際の文字数,
    DATALENGTH(@Description) AS 使用バイト数;

まとめ

ポイント

  • LEN関数は右側(末尾)の空白を自動的に除外する
  • 左側の空白はカウントされる
  • 全角スペースも末尾なら除外される
  • 実際のデータサイズを知りたい場合はDATALENGTHを使用
  • バリデーションチェックではLTRIMRTRIMの併用も検討

使い分け

  • 文字列の表示上の長さを知りたいLEN
  • データベース上の実際のサイズを知りたいDATALENGTH
  • 空白を含めた正確な文字数を知りたいDATALENGTH ÷ 2(NVARCHAR の場合)

参考リンク

Discussion

コメントにはログインが必要です。