SQL server:split字符串函数只返回字符串的一部分



我在互联网上找到了这个SQL拆分字符串函数,但当我传递一个包含700多个项目的字符串时,它只生成一个包含280行的表变量,有人能帮我确定问题出在哪里吗?

代码:

ALTER  FUNCTION [dbo].[fn_Split](@text nvarchar(MAX), @delimiter varchar(20) = ' ')
RETURNS @Strings TABLE
(    
  position int IDENTITY PRIMARY KEY,
  value nvarchar(MAX)   
)
AS
BEGIN
DECLARE @index int
SET @index = -1 
WHILE (LEN(@text) > 0) 
  BEGIN 
    SET @index = CHARINDEX(@delimiter , @text)  
    IF (@index = 0) AND (LEN(@text) > 0)  
      BEGIN  
        INSERT INTO @Strings VALUES (@text)
          BREAK  
      END 
    IF (@index > 1)  
      BEGIN  
        INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))   
        SET @text = RIGHT(@text, (LEN(@text) - @index))  
      END 
    ELSE
      SET @text = RIGHT(@text, (LEN(@text) - @index)) 
    END
  RETURN
END

这是我用来测试它的代码:

 SELECT * FROM fn_Split(@string,',');

@String is nvarchar(MAX(包含700+个项,但它只返回一个包含280行的表。

这是我提到的XML解决方案。。。

我不清楚您是如何生成@string变量的,但该方法需要更改。

<M>开始@string,以</M>结束。然后,不要使用","来分隔值,而是使用</M><M>

我在SSMS中测试了这一点,通过复制/粘贴我的字符串值并保持粘贴,直到我的行号远远超过20K。第一个LEN()实际上返回了超过19K的长度。我还展示了xml的datalength(),这只是为了演示。

我使用此方法处理供应商应用程序数据库中csv类型列中的数据,并将其转换为可用数据列。我也使用了你上面展示的方法。这个方法比我尝试过的任何其他方法都快得多。

编辑:如果这没有帮助,请告诉我们更多。你是如何生成这个@string的,也许我们可以提出一个比把它塞进csv字符串更好的选项。

希望这能有所帮助,就在这里:

DECLARE @string XML
SET @string = '<M>hello</M><M>world</M><M>hello</M><M>world</M><M>hello</M><M>world</M>'
SELECT LEN(CAST(@string AS NVARCHAR(MAX)))
SELECT DATALENGTH(@string)
SELECT Split.a.value('.', 'VARCHAR(MAX)') AS StringVal
FROM  (SELECT @string AS String) AS A 
CROSS APPLY String.nodes ('/M') AS Split(a)
--WHERE LEN(Split.a.value('.', 'VARCHAR(MAX)'))>1

以下是如果您的原始变量是VARCHAR,它将如何工作,以防将来其他人遇到这个答案。

declare @string2 varchar(max)
set @string2 = 'hello,world,hello,world,hello,world'
SELECT Split.a.value('.', 'VARCHAR(max)') AS String
FROM (SELECT CAST ('<M>' + REPLACE(CAST(@string2 AS VARCHAR(MAX)), ',', '</M><M>') + '</M>' AS XML) AS String) AS A 
CROSS APPLY String.nodes ('/M') AS Split(a)
--WHERE LEN(Split.a.value('.', 'VARCHAR(max)'))>1

如果你把csv放在一列中,你会使用这样的东西:

SELECT DISTINCT A.UserID,  
       Split.a.value('.', 'VARCHAR(max)') AS String
FROM  (SELECT UserID,  
              CAST ('<M>' + REPLACE(CAST(someCSVListColumn AS VARCHAR), ',', '</M><M>') + '</M>' AS XML) AS String  
       FROM #someTable) AS A 
CROSS APPLY String.nodes ('/M') AS Split(a)
--WHERE LEN(Split.a.value('.', 'VARCHAR(max)'))>1

尝试此函数。。。我没有时间检查你的函数逻辑。。

Create FUNCTION [dbo].[UDF_Split](@String varchar(8000), @Delimiter char(1))     
returns @temptable TABLE (ID int Identity(1,1),Value varchar(8000))     
as     
begin     
declare @idx int     
declare @slice varchar(8000)     
select @idx = 1     
    if len(@String)<1 or @String is null  return     
while @idx!= 0     
begin     
    set @idx = charindex(@Delimiter,@String)     
    if @idx!=0     
        set @slice = left(@String,@idx - 1)     
    else     
        set @slice = @String     
    if(len(@slice)>0)
        insert into @temptable(Value) values(@slice)     
    set @String = right(@String,len(@String) - @idx)     
    if len(@String) = 0 break     
end 
return     
end

最新更新