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

Jas*_*ers 102 sql-server

我在SQL Server 2005中有以下测试表:

CREATE TABLE [dbo].[TestTable]
(
 [ID] [int] NOT NULL,
 [TestField] [varchar](100) NOT NULL
) 
Run Code Online (Sandbox Code Playgroud)

填充:

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

当我尝试使用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
Run Code Online (Sandbox Code Playgroud)

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

Jas*_*ers 117

Microsoft在MSDN中明确记录了这一点,网址http://msdn.microsoft.com/en-us/library/ms190329(SQL.90).aspx,其中指出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
Run Code Online (Sandbox Code Playgroud)

  • 注意:对于`DATALENGTH`,如果被测试的表达式是宽字符类型(Unicode; nchar,nvarchar或ntext),则还需要将结果除以2,因为结果是*bytes*,而不是*characters*. (48认同)
  • 我会使用`LEN(REPLACE(','','_'))`.这应该与`varchar`和`nvarchar`以及包含特殊unicode控制字符的字符串一起使用. (17认同)
  • 同样对于`varchar`等,这可以是与校对有关的,即使是2的直接除法也是不可靠的.见[这里的例子](http://stackoverflow.com/questions/176514/what-is-the-difference-between-char-nchar-varchar-and-nvarchar-in-sql-server/8250586#8250586) (7认同)
  • -1,`DATALENGTH()`不应该被认为是计算字符的另一种方法,因为它计算字节而不是字符,这在`VARCHAR` /`NVARCHAR`中表示相同的字符串时很重要. (5认同)
  • 从SQL Server 2012开始,具有版本100排序规则的unicode列现在支持代理项对.这意味着单个字符最多可使用4个字节,导致除以两个技巧失败.参见[msdn](https://msdn.microsoft.com/en-us/library/ms143726.aspx#Supplementary_Characters). (4认同)

Ser*_*rge 78

你可以使用这个技巧:

LEN(Str +'x') - 1

  • 你能用更好的替代品来启发我们吗?数据长度肯定不是. (14认同)
  • 我强烈反对使用不一致的方法(在某些情况下,你将结果除以2,有时不是)是一个更好的选择.也许我的方法可能会有接近于零的性能影响. (14认同)
  • 到目前为止,这是最好,最优雅的解决方案.我真的不在乎它是否感觉像是黑客(编码不是感觉),我真的很在乎这个解决方案没有副作用的事实.我可以更改数据类型varchar/nvarchar,它仍然有效.做得好. (9认同)
  • @usr Serge的方法是最好的,恕我直言.简单而优雅.DATALENGTH很复杂:依赖于单/双字节类型,依赖于校对/语言等. (5认同)
  • 由于这种副作用,有一个警告.如果你正在使用nvarchar(4000)类型的变量,并且你的变量包含4000个字符的字符串,那么添加的字符将被忽略,你将得到错误的结果(SQL的len忽略尾随空格,少于1你减去). (5认同)
  • @Henesnarfel:`LEN`已经计入领先空白,所以不需要额外的前缀. (2认同)
  • @Serge 如果输入字符串正好在最大类型长度(例如`DECLARE @x VARCHAR(8000) = '{8000 chars}'; SELECT LEN(@x + 'x') -- 返回8000` )。似乎我们需要将 STR 包装为 `CONVERT(NVARCHAR(MAX), Str)` 以对任何字符串类型完全健壮 (2认同)
  • @hatchet 我相信这将说明警告: LEN(CAST(Str AS nvarchar(MAX)) + 'x') - 1 (2认同)

TTT*_*TTT 14

我用这个方法:

LEN(REPLACE(TestField, ' ', '.'))
Run Code Online (Sandbox Code Playgroud)

我比DATALENGTH更喜欢这个,因为它适用于不同的数据类型,我更喜欢在最后添加一个字符,因为你不必担心字符串已经达到最大长度的边缘情况.

注意:我会在针对非常大的数据集使用它之前测试性能; 虽然我刚刚对2M行进行了测试,但没有REPLACE它并不慢于LEN ......


cro*_*sek 12

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

你得到某人提交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

  • `datalength`解决方案从SQL Server 2012开始更差,因为它现在支持UTF-16中的代理对,这意味着一个字符最多可以使用4个字节.他们确实需要修复`len`函数来遵守ANSI,或者至少提供一个专用函数来计算char,包括尾随空格. (2认同)

hat*_*ica 8

两个最高投票答案存在问题.答案建议DATALENGTH容易出现程序员错误.DATALENGTH对于NVARCHAR类型,结果必须除以2 ,而不是VARCHAR类型.这需要知道您获得的类型的长度,如果该类型发生变化,您必须努力改变您使用的位置DATALENGTH.

最受欢迎的答案也存在问题(我承认这是我首选的方法,直到这个问题出现在我身上).如果您获得的长度是类型NVARCHAR(4000),并且它实际上包含4000个字符的字符串,SQL将忽略附加的字符而不是隐式地将结果转换为NVARCHAR(MAX).最终结果是长度不正确.VARCHAR(8000)也会发生同样的事情.

我发现的东西几乎和普通老字号一样快LEN,比LEN(@s + 'x') - 1大字符串快,并且不假设底层字符宽度如下:

DATALENGTH(@s) / DATALENGTH(LEFT(LEFT(@s, 1) + 'x', 1))
Run Code Online (Sandbox Code Playgroud)

这将获取数据长度,然后除以字符串中单个字符的数据长度.'x'的附加涵盖了字符串为空的情况(在这种情况下将除以零).这工作是否@sVARCHARNVARCHAR.LEFT当字符串很大时,在追加前做一个字符会刮胡子.但问题是,对于包含代理项对的字符串,它无法正常工作.

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

鉴于代理对对任何使用的技术引入的问题DATALENGTH,我认为最安全的方法给出了我所知道的正确答案如下:

LEN(CONVERT(NVARCHAR(MAX), @s) + 'x') - 1
Run Code Online (Sandbox Code Playgroud)

这比REPLACE技术更快,并且使用更长的字符串会更快.基本上这种技术是LEN(@s + 'x') - 1技术,但是对边缘情况的保护,其中字符串的长度为4000(对于nvarchar)或8000(对于varchar),因此即使对此也给出了正确的答案.它还应该正确处理具有代理对的字符串.

  • @Douglas - 这是有用的信息.如果只有微软会给我们一个不忽略尾随空格的LEN版本. (7认同)

小智 6

默认情况下 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)
Run Code Online (Sandbox Code Playgroud)

当然不要将它用于前导空格。

  • 现在它修剪 ** 前导** 空格而不是尾随空格。同一天,不同的问题:) (9认同)

Rem*_*anu 5

您还需要确保使用尾随空白实际保存数据.当ANSI PADDING为OFF(非默认值)时:

插入varchar列的字符值中的尾随空白被修剪.

  • 我认为你不应该关闭ANSI PADDING,因为这个设置已经过时了.使其处于非标准值会导致许多小问题. (3认同)