为什么在T-SQL中LEN(char(32))= 0?

时间:2019-05-15 22:18:58

标签: sql-server tsql

我想编写一个函数来计算文本字符串中定界符或任何子字符串(可能是空格)的数量,如果定界符为null或为空,则会引发hack错误:

if len(@lookfor)=0 or @lookfor is null return Cast('substring must not be null or empty' as int)

但是如果使用@lookfor =''调用该函数,则会触发错误。

我知道DATALENGTH()。只是好奇为什么在前面没有任何内容的情况下将单个空格视为“尾随”。

2 个答案:

答案 0 :(得分:3)

  

我知道DATALENGTH()。只是好奇为什么要对待一个空格   如果之前没有任何内容,则表示为“尾随”。

之所以拖尾是因为它在字符串的末尾。它从一开始就处于领先地位。

  
    

但是如果使用@lookfor =''调用该函数,则会触发错误

  

使很多人不满意SQL的事情是''='';请注意以下查询:

DECLARE @blank VARCHAR(10) = '', @space VARCHAR(10) = CHAR(32);
SELECT CASE WHEN @blank = @space THEN 'That the...!?!?' END;

您可以将@space更改为CHAR(32)+ CHAR(32)+ ....,并且@space和@blank仍然相等。

使事情复杂一点的是,空白/空值的DATALENGTH为VARCHAR(N)时为0,而对于CHAR(N)值则DATALENGTH为N。换一种说法, SELECT DATALENGTH(CAST('' AS CHAR(1)))返回1,SELECT DATALENGTH(CAST('' AS CHAR(10)))返回10。

这意味着,如果您的定界符变量为CHAR(1)-则会使您陷入困境。这是为您提供的功能:

CREATE FUNCTION dbo.CountDelimiters(@string VARCHAR(8000), @delimiter VARCHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS RETURN
SELECT DCount = MAX(DATALENGTH(@string)-LEN(REPLACE(@string,@delimiter,'')))
WHERE  DATALENGTH(@delimiter) > 0;

请注意,@ delimter是VARCHAR(1),是CHAR数据类型。

计算@string中的分隔符的公式为:

DATALENGTH(@string)-LEN(REPLACE(@string,@delimiter,''))

(DATALENGTH(@string)-LEN(REPLACE(@string,@delimiter,'')))/DATALENGTH(@delimiter)处理大于1`的分隔符。

WHERE DATALENGTH(@delimiter) > 0将强制函数忽略NULL或空白值。这就是启动谓词

DATALENGTH(@string)-LEN(REPLACE(@string,@delimiter,''))周围放置一个MAX会在您将其传递为空白或NULL值的情况下强制该函数返回NULL值。

这将为我的字符串中的空格数返回10:

SELECT f.DCount FROM dbo.CountDelimiters('one space  two spaces   three   ', CHAR(32)) AS f;

在表格上,您将使用如下功能(请注意,我是在计算字母“ A”出现的次数:

-- Sample Strings
DECLARE @table TABLE (SomeText VARCHAR(36));
INSERT @table VALUES('ABCABC'),('XXX'),('AAA'),(''),(NULL);

SELECT      t.SomeText, f.DCount    
FROM        @table                               AS t
CROSS APPLY dbo.CountDelimiters(t.SomeText, 'A') AS f;

返回哪个:

SomeText                             DCount
------------------------------------ -----------
ABCABC                               2
XXX                                  0
AAA                                  3
                                     0
NULL                                 NULL

答案 1 :(得分:1)

如果字符串的末尾有一个字符,则即使该字符串前面没有其他字符,也将其视为结尾。关于主角的逻辑也是如此。

因此' '可以被认为是带有尾部空格的空字符串('')。

当我开始使用SQL时,我还注意到LEN函数忽略尾随空格的行为。而且我认为(但我不确定)与LEN在与CHAR / NCHAR值一起使用时也可能表现为“正确”有关。与VARCHAR / NVARCHAR不同,CHAR / NCHAR值具有固定宽度,并且将自动用尾随空格填充。因此,当您将值'abc'放入类型为CHAR(5)的字段/变量中时,该值将变为'abc ',但在这种情况下LEN函数仍将“正确”返回3。

我认为这只是SQL的一个怪癖。

备注:

DATALENGTH函数将不会忽略VARCHAR / NVARCHAR值中的尾随空格。但请注意,DATALENGTH将返回该字段值的大小(以字节为单位)。因此,如果您使用Unicode数据(NCHAR / NVARCHAR),则DATALENGTH函数将为值N'abc'返回6,因为SQL Server中的每个Unicode字符都使用2个字节!