SQL Serverの末尾のスペースを含まないLEN関数


109

SQL Server 2005には次のテストテーブルがあります。

CREATE TABLE [dbo].[TestTable]
(
 [ID] [int] NOT NULL,
 [TestField] [varchar](100) NOT NULL
) 

人口:

INSERT INTO TestTable (ID, TestField) VALUES (1, 'A value');   -- Len = 7
INSERT INTO TestTable (ID, TestField) VALUES (2, 'Another value      '); -- Len = 13 + 6 spaces

SQL ServerのLEN()関数でTestFieldの長さを見つけようとすると、末尾のスペースがカウントされません-例:

-- Note: Also results the grid view of TestField do not show trailing spaces (SQL Server 2005).
SELECT 
 ID, 
 TestField, 
 LEN(TestField) As LenOfTestField, -- Does not include trailing spaces
FROM 
 TestTable

長さの結果に末尾のスペースを含めるにはどうすればよいですか?


1
ここでの本当の解決策は、マイクロソフトが壊れたソフトウェアを修正することかもしれないと思います。ここに投票:feedback.azure.com/forums/908035-sql-server/suggestions/...
QAコレクティブ

回答:


125

これは、MSDNのhttp://msdn.microsoft.com/en-us/library/ms190329(SQL.90).aspxでMicrosoftによって明確に文書化されており、LENは指定された文字列式の文字数を返します。末尾の空白」。ただし、注意しないと見落とすのは簡単です。

代わりにDATALENGTH関数を使用する必要があります。http://msdn.microsoft.com/en-us/library/ms173486(SQL.90).aspxを参照してください。「式を表すために使用されるバイト数を返します」。

例:

SELECT 
    ID, 
    TestField, 
    LEN(TestField) As LenOfTestField,           -- Does not include trailing spaces
    DATALENGTH(TestField) As DataLengthOfTestField      -- Shows the true length of data, including trailing spaces.
FROM 
    TestTable

52
注:DATALENGTHテスト対象の式がワイド文字タイプ(Unicode; nchar、nvarcharまたはntext)の場合、結果は文字ではなくバイトであるため、結果を2で除算する必要もあります。
devstuff

7
また、varcharなどの場合、これは照合に依存する可能性があり、2による単純な除算でも信頼できません。ここの例を
マーティン・スミス

18
使用しますLEN(REPLACE(expr, ' ', '_'))。これはvarcharnvarchar特別なユニコード制御文字を含むand およびstringで動作するはずです。
Olivier Jacot-Descombes 14

6
-1は、DATALENGTH()文字ではなくバイトをカウントするため、文字をカウントする別の方法と見なすべきではありません。これは、VARCHAR/で同じ文字列を表す場合に重要NVARCHARです。
binki 14

5
SQL Server 2012以降、照合順序がバージョン100のUnicode列はサロゲートペアをサポートするようになりました。これは、単一の文字が最大4バイトを使用する可能性があり、2による除算が失敗する原因になることを意味します。msdnを参照してください。
フレデリック

85

あなたはこのトリックを使うことができます:

LEN(Str + 'x')-1


15
より良い代替案を教えていただけませんか?データ長は確かではありません。
セルジュ

15
一貫性のない方法を使用する(場合によっては、結果を2で除算し、場合によっては2で除算しない)方が良いオプションであることに強く反対します。たぶん、私の方法では、ほぼゼロのパフォーマンスヒットがあります。
セルジュ

5
@usr Sergeの方法が最高です。シンプルでエレガント。DATALENGTHは複雑です:シングル/ダブルバイトタイプ依存、照合/言語依存など
TA Mr.

10
これは、これまでで最高のエレガントなソリューションです。私はそれがハックのように感じるかどうかは気にしません(コーディングは感情に関するものではありません)。私はこのソリューションに副作用がないという事実に本当に気にします。データ型varchar / nvarcharを変更できますが、それでも機能します。よくやった。
マイクケスキノフ2014年

5
この副作用のため、注意が必要です。タイプnvarchar(4000)の変数を使用していて、変数に4000文字の文字列が含まれている場合、追加された文字は無視され、誤った結果(末尾のスペースを無視するSQLのlen、1未満あなたが引く)。
手斧-SOverflowを使用して、2015年

17

私はこの方法を使用します:

LEN(REPLACE(TestField, ' ', '.'))

これはさまざまなデータ型で機能するため、DATALENGTHよりもこれを好みます。また、文字列がすでに最大長になっているエッジケースについて心配する必要がないため、最後に文字を追加するよりも好みです。

注:非常に大きなデータセットに対して使用する前に、パフォーマンスをテストします。2M行に対してテストしただけで、REPLACEなしのLENより遅くはありませんでした...


14

「長さの結果に末尾のスペースを含めるにはどうすればよいですか?」

この驚くほど単純な問題に対する上記の回避策のほとんどすべてに欠陥があるか非効率的であるため、誰かにSQL Server拡張要求/バグレポートを提出してもらいます。これはSQL Server 2012でも当てはまるようです。自動トリミング機能はANSI / ISO SQL-92に由来している可能性がありますが、いくつかの穴(またはそれらのカウント不足)があるようです。

ここで「LENが末尾の空白をカウントするように設定を追加」に投票してください。

https://feedback.azure.com/forums/908035-sql-server/suggestions/34673914-add-setting-so-len-counts-trailing-whitespace

廃止された接続リンク:https : //connect.microsoft.com/SQLServer/feedback/details/801381


2
datalengthそれが今の文字は4つのバイトまで使用することができますを意味し、UTF-16でサロゲートペアをサポートしていないので、解決策はさらに悪化、SQLサーバー2012年から始まっています。lenANSIに準拠するように関数を修正するとき、または少なくとも末尾のスペースを含む文字をカウントするための専用関数を提供するときです。
フレデリック

1
このためには、フィードバックリンクをさらに使用する必要があります。この問題がインターネット経由でしか検索できないのは困惑しています。LEN()関数が切断の原因であるとさえ考える前に、自分のコードのどこに誤りがあるのか​​を突き止めるのに2時間近く費やしました。
Takophiliac

私はこれに同意しますが、パラメーターで空白を削除できるようにする必要があります。これにより、EFとの文字列比較がはるかに簡単になり、iqueryable式の作成時に空白が含まれているかどうかを確認する必要がなくなります。
ganjeii

9

上位2つの回答には問題があります。推奨する答えDATALENGTHは、プログラマーのエラーになりがちです。の結果はDATALENGTHNVARCHAR型の場合は2 ではなく、型の場合は2で除算する必要がありVARCHARます。これには、長さを取得するタイプの知識が必要です。そのタイプが変更されDATALENGTHた場合、使用した場所を入念に変更する必要があります。

最も賛成された回答にも問題があります(この問題が私に噛み付くまで、私はそれを行うための私の好ましい方法であったことを認めます)。長さを取得するものがtype NVARCHAR(4000)であり、実際に4000文字のストリングが含まれている場合、SQLは結果を暗黙的にキャストするのではなく、追加された文字を無視しNVARCHAR(MAX)ます。最終結果は不正確な長さです。同じことがVARCHAR(8000)でも起こります。

私が見つけたものは機能し、普通のoldとほぼ同じ速さであり、大きな文字列のLEN場合よりも速くLEN(@s + 'x') - 1、基礎となる文字幅が以下であると想定していません:

DATALENGTH(@s) / DATALENGTH(LEFT(LEFT(@s, 1) + 'x', 1))

これはデータ長を取得し、文字列の1文字のデータ長で除算します。「x」の追加は、文字列が空の場合をカバーします(その場合、ゼロで除算されます)。これ@sは、VARCHARまたはのどちらでも機能しNVARCHARます。LEFT追加の前に1文字のofを実行すると、文字列が大きいときに一部の時間が削られます。ただし、この問題は、サロゲートペアを含む文字列では正しく機能しないことです。

受け入れられた回答へのコメントで言及されている別の方法がありREPLACE(@s,' ','x')ます。その手法は正しい答えを与えますが、文字列が大きい場合、他の手法よりも数桁遅くなります。

を使用する任意の手法でサロゲートペアによって発生する問題DATALENGTHを考えると、私が知っている正しい答えを与える最も安全な方法は次のとおりです。

LEN(CONVERT(NVARCHAR(MAX), @s) + 'x') - 1

これはREPLACEテクニックよりも速く、より長い文字列でははるかに速くなります。基本的にこの手法は手法ですLEN(@s + 'x') - 1が、文字列の長さが4000(nvarcharの場合)または8000(varcharの場合)であるエッジケースを保護するため、その場合でも正しい答えが得られます。また、サロゲートペアを含む文字列を正しく処理する必要があります。


1
残念ながら、この答えは、もはや上の操作を実行しているSQL Serverの2012年にサロゲートペアを含む文字列のために働くんN'x𤭢x' COLLATE Latin1_General_100_CI_AS_SCしながら、4を与えるLEN3.与え
ダグラス

9
@ダグラス-それは有用な情報です。マイクロソフトだけが末尾のスペースを無視しないLENのバージョンを私たちに提供してくれるなら。
手斧-2015年

5

また、データが末尾の空白とともに実際に保存されるようにする必要もあります。ときANSI PADDINGが OFF(非デフォルト)です。

varchar列に挿入された文字値の末尾の空白は削除されます。


3
この設定は廃止されているため、ANSI PADDINGをオフにしないでください。非標準の値にすると、多くの小さな問題が発生します。
usr

4

LENはデフォルトで末尾のスペースをカットするので、前に移動すると機能することがわかりました

(LEN(REVERSE(TestField))

だからあなたが望むなら、あなたは言うことができます

SELECT
t.TestField,
LEN(REVERSE(t.TestField)) AS [Reverse],
LEN(t.TestField) AS [Count]
FROM TestTable t
WHERE LEN(REVERSE(t.TestField)) <> LEN(t.TestField)

もちろん、これを先頭のスペースに使用しないでください。


9
末尾のスペースではなく、先頭のスペースを削除するようになりました。同日、別の問題:)
リバースエンジニア

@DaveBoltman私の提案はおそらくもっと複雑ですが、TRIMされた長さと比較することもできます。
ブライアンJ

これは、末尾のスペースではなく先頭のスペースがカウントされないというバグを逆にします。次のコードを参照してください: declare @TestField varchar(10); SET @TestField = ' abc '; -- Length with spaces is 5. select LEN(REVERSE(@TestField)) -- Returns 4 select LEN(@TestField) -- Returns 4
Metalogic

1

文字列の連結が嫌いな場合は、文字列の長さフィールドを返すCLR関数を定義する必要があります。私LEN('x' + @string + 'x') - 2は本番のユースケースで使用しています。


0

DATALENGTHn / varcharの問題が原因で嫌いな場合は、次のようにしてください。

select DATALENGTH(@var)/isnull(nullif(DATALENGTH(left(@var,1)),0),1)

それはちょうどです

select DATALENGTH(@var)/DATALENGTH(left(@var,1))

ゼロ除算保護でラップされています。

単一の文字のDATALENGTHで割ることにより、長さを正規化します。

(もちろん、それが問題である場合でも、サロゲートペアに問題があります。)


-4

SELECT DATALENGTH( 'string')を使用してください


2
あなたは7年前から他の人の答えを言い直し、何も新しいものを提供したり、あなたの答えが何をするか、それがその質問にどのように答えるかを説明したりしました。
Jpsh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.