LEN函数不包括SQL Server中的尾随空格

我在SQL Server 2005中有以下testing表:

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 

如何在长度结果中包含尾随空格?

这是Microsoft在MSDN中明确logging在http://msdn.microsoft.com/en-us/library/ms190329(SQL.90).aspx ,其中指出LEN“返回指定的stringexpression式的字符数,排除尾随空白“。 但是,如果你不谨慎,这是一个简单的细节。

您需要改为使用DATALENGTH函数 – 请参阅http://msdn.microsoft.com/en-us/library/ms173486(SQL.90).aspx – 哪个“返回用于表示任何expression式的字节数”。

例:

 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 

你可以使用这个技巧:

LEN(Str +'x') – 1

“如何在长度结果中包含尾随空格?”

你得到一个人提交一个SQL Server增强请求/错误报告,因为几乎所有列出的解决这个令人惊讶的简单问题的解决方法有一些缺陷或效率低下。 这在SQL Server 2012中似乎仍然是正确的。自动修剪function可能源自ANSI / ISO SQL-92,但似乎存在一些漏洞(或缺less对它们的计数)。

请投票: https : //connect.microsoft.com/SQLServer/feedback/details/801381

我用这个方法:

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

我比DATALENGTH更喜欢这个,因为它适用于不同的数据types,我更喜欢通过添加一个字符到最后,因为您不必担心string已经处于最大长度的边缘情况。

注意:在对一个非常大的数据集使用之前,我会testing性能; 虽然我只是testing它对2M行,它不比没有REPLACE的LEN慢…

这两个顶级投票答案有问题。 推荐DATALENGTH的答案很容易出现程序员错误。 对于NVARCHARtypes, DATALENGTH的结果必须除以2,对于VARCHARtypes则不能。 这需要知道你获得长度的types,如果types改变,你必须努力改变你使用DATALENGTH的地方。

最高的答案也是一个问题(我承认这是我的首选方法,直到这个问题发生在我身上)。 如果获得的长度是NVARCHAR(4000)types,并且实际上包含4000个字符的string,则SQL将忽略附加字符,而不是隐式地将结果转换为NVARCHAR(MAX) 。 最终结果是不正确的长度。 VARCHAR(8000)会发生同样的情况。

我发现的作品几乎和普通的老LEN一样快,比大string的LEN(@s + 'x') - 1更快,并且不假定底层字符宽度如下:

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

这会得到数据长度,然后用string中的单个字符的数据长度进行分割。 'x'的附加部分覆盖了string为空的情况(在这种情况下,除以零)。 这是否工作是否是VARCHARNVARCHAR 。 当string很大时,在追加之前做1个字符的LEFT 。 但是,这个问题是,它不能正确使用包含代理对的string。

在接受的答案的评论中提到了另一种方法,使用REPLACE(@s,' ','x') 。 这种技术给出了正确的答案,但是当string很大时,比其他技术慢了几个数量级。

考虑到使用DATALENGTH技术的代理对引入的问题,我认为给出正确答案的最安全的方法我知道的是:

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

这比REPLACE技术更快,用更长的string更快。 基本上这种技术是LEN(@s + 'x') - 1技术,但是对于string长度为4000(对于nvarchar)或8000(对于varchar)的边缘情况的保护,以便正确的答案是即使这样。 它也应该正确处理代理对的string。

您还需要确保您的数据实际上是以尾随空格保存的。 当ANSI PADDING为OFF(非默认值)时:

在插入到varchar列的字符值中,尾随空白被剪裁。

LEN在默认情况下会削减尾随空格,所以我发现这个function在您将它们移动到前面时会发挥作用

(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) 

当然,不要使用这个空格。

如果你不喜欢string连接,你应该定义一个返回string长度字段的CLR函数。 我在我的生产用例中使用了LEN('x' + @string + 'x') - 2

使用SELECT DATALENGTH('string')

如果你不喜欢DATALENGTH是因为n / varchar的问题,那怎么样:

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

这只是

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

包裹着零分保护。

通过除以单个字符的DATALENGTH,我们得到长度标准化。

(当然,如果这是一个问题,仍然存在代理对的问题。)