简体   繁体   English

用于根据指定的分隔符将字符串拆分为子字符串行的 iTVF 在接收到空值时中断 (TSQL)

[英]iTVF for splitting string into row of substrings based on a specified separator character breaks when received empty value (TSQL)

I have an inline table-valued function, which splits strings into row of substrings based on a specified separator.我有一个内联表值 function,它根据指定的分隔符将字符串拆分为子字符串行。

It is as follows:它是这样的:

ALTER FUNCTION [dbo].[SplitString]
    (@List NVARCHAR(MAX),
     @Delim VARCHAR(255))
RETURNS TABLE
AS
    RETURN 
        (SELECT [Value], idx = RANK() OVER (ORDER BY n) 
         FROM 
             (SELECT 
                  n = Number, 
                  [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
                  CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
              FROM 
                  (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
                   FROM sys.all_objects) AS x
              WHERE Number <= LEN(@List)
                AND SUBSTRING(@Delim + @List, [Number], LEN(@Delim)) = @Delim) AS y
        );
GO

Usage:用法:

SELECT value 
FROM dbo.SplitString('a|b|c', '|')  

returns:回报:

value价值
a一种
b b
c c

But when sending an empty value as the first argument, it doesn't return anything.但是当发送一个空值作为第一个参数时,它不会返回任何东西。

For example:例如:

SELECT value FROM dbo.SplitString('','|')     

This doesn't return anything.这不会返回任何东西。

What modification I need to do to the dbo.SplitString function, so that it returns an empty result set, when an empty string is passed in as first argument?我需要对dbo.SplitString function 做哪些修改,以便在将空字符串作为第一个参数传入时返回空结果集?

PS: I can't use the inbuilt STRING_SPLIT function because of compatibility issues. PS:由于兼容性问题,我无法使用内置的STRING_SPLIT function。

DelimitedSplit8K_LEAD (above) will always return a row and will be faster. DelimitedSplit8K_LEAD(上图)将始终返回一行并且会更快。

That said, for learning purposes let's fix your function. If you replace a blank value with your delimiter you will get the results you are looking for.也就是说,出于学习目的,让我们修复您的 function。如果您将空白值替换为分隔符,您将获得所需的结果。 You just need to replace every instance of @list with ISNULL(NULLIF(@List,''),@Delim).您只需要用 ISNULL(NULLIF(@List,''),@Delim) 替换@list with每个实例。 Now you have:现在你有:

ALTER FUNCTION [dbo].[SplitString]
    (@List NVARCHAR(MAX),
     @Delim VARCHAR(255))
RETURNS TABLE
AS
    RETURN 
        (SELECT [Value], idx = RANK() OVER (ORDER BY n) 
         FROM 
             (SELECT 
                  n = Number, 
                  [Value] =     LTRIM(RTRIM(SUBSTRING(ISNULL(NULLIF(@List,''),@Delim), [Number],
              CHARINDEX(@Delim, ISNULL(NULLIF(@List,''),@Delim) + @Delim, [Number]) - [Number])))
              FROM 
                  (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
                   FROM sys.all_objects) AS x
              WHERE Number <= LEN(ISNULL(NULLIF(@List,''),@Delim))
                AND SUBSTRING(@Delim + ISNULL(NULLIF(@List,''),@Delim),         
[Number], LEN(@Delim)) = @Delim) AS y
        );

Now, when you execute: DECLARE @list VARCHAR(max) = '', @delim VARCHAR(255) = '|'现在,当你执行: DECLARE @list VARCHAR(max) = '', @delim VARCHAR(255) = '|'

SELECT *
FROM dbo.SplitString(@list,@delim)

You get:你得到:

Value    idx
------   ------
         1

Thanks @Larnu and @Bernie for all suggestions.感谢@Larnu 和@Bernie 的所有建议。
After so much of research, I started iterating and getting expected result.经过大量研究,我开始迭代并获得预期结果。 I achieved this by simple while loop and, string functions of SQL.我通过简单的 while 循环和 SQL 的字符串函数实现了这一点。

CREATE FUNCTION [SplitString]
(
   @ActualString      VARCHAR(MAX),
   @DelimiterCharacter  VARCHAR(10)
)
RETURNS @TableRes TABLE (Id INT IDENTITY(1,1),Value VARCHAR(MAX))
AS
BEGIN
DECLARE @SubStr VARCHAR(MAX)
     WHILE (CHARINDEX(@DelimiterCharacter  ,@ActualString)<>0)
     BEGIN
         SET @SubStr=SUBSTRING(@ActualString,1,CHARINDEX(@DelimiterCharacter ,@ActualString)-1)
         SET @ActualString= STUFF(@ActualString,1,CHARINDEX(@DelimiterCharacter,@ActualString),'') 
         INSERT INTO @TableRes
         SELECT @SubStr

      END
       INSERT INTO @TableRes
       SELECT @ActualString


       RETURN
END

This will work for all cases这将适用于所有情况
1)When Actual string is empty string like select * from [dbo].[SplitString]('',',') 1)当实际字符串为空字符串时,如select * from [dbo].[SplitString]('',',')
2)When Actual string has empty string at end like select * from [dbo].[SplitString]('a,b,',',') 2)当实际字符串在末尾有空字符串时,如select * from [dbo].[SplitString]('a,b,',',')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM