将两个分隔符的字符串拆分为两列

时间:2022-09-03 21:47:50

I have a string value which has numeric values separated by comma and then by a pipe. I want to split them into a table with two columns. I could split the string by one delimiter but unfortunately couldn't find a way to split by two. Please help.

我有一个字符串值,其数字值以逗号分隔,然后由管道分隔。我想把它们分成一个有两列的表。我可以将字符串拆分一个分隔符,但遗憾的是找不到拆分方法。请帮忙。

DECLARE @list NVARCHAR(MAX) = '1,101|2,202|3,303';

The result should be like below.

结果应如下所示。

1   101
2   202
3   303

Thanks in advance.

提前致谢。

4 个解决方案

#1


1  

If you're using SQL Server 2016 or Azure, you have access to the new SPLIT_STRING function. If not I recommend using Jeff Moden's DelimitedSplit8K function, which is widely regarded as the fastest, most efficient SQL based string splitter available...

如果您使用的是SQL Server 2016或Azure,则可以访问新的SPLIT_STRING函数。如果不是,我建议使用Jeff Moden的DelimitedSplit8K函数,它被广泛认为是最快,最有效的基于SQL的字符串分割器...

DECLARE @list NVARCHAR(MAX) = '1,101|2,202|3,303';

SELECT 
    Col1 = LEFT(dsk.Item, sl.SplitLocation - 1),
    Col2 = SUBSTRING(dsk.Item, sl.SplitLocation + 1, LEN(dsk.Item))
FROM 
    dbo.DelimitedSplit8K(@list, '|') dsk    -- code for DelimitedSplit8K can be found here... http://www.sqlservercentral.com/articles/Tally+Table/72993/
    CROSS APPLY ( VALUES (ISNULL(NULLIF(CHARINDEX(',', dsk.Item, 1), 0), 1)) ) sl (SplitLocation);

#2


0  

CREATE  FUNCTION [dbo].[fn_Split_char](@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 LEFT(value, Charindex(',', value) - 1) ,
RIGHT(value, Charindex(',', Reverse(value)) - 1) ,
* from [fn_Split_char] ('1,101|2,202|3,303', '|')

#3


0  

Use xml path and cross apply to create multiple rows for a single row based on the pipe separator and then use substring w.r.t the commas to derive two desired columns

使用xml路径并交叉应用以基于管道分隔符为单行创建多个行,然后使用子字符串w.r.t逗号来派生两个所需的列

Create table #temp(list nvarchar(max))
Insert into #temp values('1,101|2,202|3,303')
SELECT 
  Substring(Tbl.Col.value('./text()[1]','varchar(50)'),1,1)as col1,
  Substring(Tbl.Col.value('./text()[1]','varchar(50)'),charindex(',',Tbl.Col.value('./text()[1]','varchar(50)'),1)+1,len(Tbl.Col.value('./text()[1]','varchar(50)')))
FROM 
(Select cast('<a>'+ replace((SELECT list As [*] FOR XML PATH  ('')), '|', '</a><a>') + '</a>' as xml)as t 
  from #temp) tl
Cross apply 
tl.t.nodes('/a') AS Tbl(Col)

#4


0  

Try using this Table-valued Function, embed this SP to your main SP

尝试使用此表值函数,将此SP嵌入到主SP中

ALTER FUNCTION [dbo].[delimiter]
(
@PARAM_IDS AS VARCHAR(MAX)
@PARAM_DELIMITER AS CHAR(1)
)
RETURNS 
@NEW_TABLE TABLE 
(
NUM INT NOT NULL IDENTITY,
ID INT NOT NULL
)
AS
BEGIN
DECLARE @NEXTSTRING AS NVARCHAR(MAX);
DECLARE @POS AS INT;
DECLARE @STRING AS NVARCHAR(MAX);
DECLARE @DELIMITER AS NVARCHAR(MAX);
SET @STRING = @PARAM_IDS;
SET @DELIMITER = @PARAM_DELIMITER;
SET @STRING = @STRING + @DELIMITER;
SET @POS = CHARINDEX(@DELIMITER,@STRING);

WHILE (@POS <> 0)
BEGIN
    SET @NEXTSTRING = SUBSTRING(@STRING,1,@POS - 1);
    INSERT @NEW_TABLE (ID) VALUES (@NEXTSTRING);
    SET @STRING = SUBSTRING(@STRING,@POS+1,len(@STRING));
    SET @POS = CHARINDEX(@DELIMITER,@STRING);
END 
    RETURN
END

then example of use

然后使用的例子

SET @DETAILS_COUNT = (SELECT COUNT(*) FROM delimiter(@PARAM_MS_UNIT_ID, @DELIMITER));

#1


1  

If you're using SQL Server 2016 or Azure, you have access to the new SPLIT_STRING function. If not I recommend using Jeff Moden's DelimitedSplit8K function, which is widely regarded as the fastest, most efficient SQL based string splitter available...

如果您使用的是SQL Server 2016或Azure,则可以访问新的SPLIT_STRING函数。如果不是,我建议使用Jeff Moden的DelimitedSplit8K函数,它被广泛认为是最快,最有效的基于SQL的字符串分割器...

DECLARE @list NVARCHAR(MAX) = '1,101|2,202|3,303';

SELECT 
    Col1 = LEFT(dsk.Item, sl.SplitLocation - 1),
    Col2 = SUBSTRING(dsk.Item, sl.SplitLocation + 1, LEN(dsk.Item))
FROM 
    dbo.DelimitedSplit8K(@list, '|') dsk    -- code for DelimitedSplit8K can be found here... http://www.sqlservercentral.com/articles/Tally+Table/72993/
    CROSS APPLY ( VALUES (ISNULL(NULLIF(CHARINDEX(',', dsk.Item, 1), 0), 1)) ) sl (SplitLocation);

#2


0  

CREATE  FUNCTION [dbo].[fn_Split_char](@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 LEFT(value, Charindex(',', value) - 1) ,
RIGHT(value, Charindex(',', Reverse(value)) - 1) ,
* from [fn_Split_char] ('1,101|2,202|3,303', '|')

#3


0  

Use xml path and cross apply to create multiple rows for a single row based on the pipe separator and then use substring w.r.t the commas to derive two desired columns

使用xml路径并交叉应用以基于管道分隔符为单行创建多个行,然后使用子字符串w.r.t逗号来派生两个所需的列

Create table #temp(list nvarchar(max))
Insert into #temp values('1,101|2,202|3,303')
SELECT 
  Substring(Tbl.Col.value('./text()[1]','varchar(50)'),1,1)as col1,
  Substring(Tbl.Col.value('./text()[1]','varchar(50)'),charindex(',',Tbl.Col.value('./text()[1]','varchar(50)'),1)+1,len(Tbl.Col.value('./text()[1]','varchar(50)')))
FROM 
(Select cast('<a>'+ replace((SELECT list As [*] FOR XML PATH  ('')), '|', '</a><a>') + '</a>' as xml)as t 
  from #temp) tl
Cross apply 
tl.t.nodes('/a') AS Tbl(Col)

#4


0  

Try using this Table-valued Function, embed this SP to your main SP

尝试使用此表值函数,将此SP嵌入到主SP中

ALTER FUNCTION [dbo].[delimiter]
(
@PARAM_IDS AS VARCHAR(MAX)
@PARAM_DELIMITER AS CHAR(1)
)
RETURNS 
@NEW_TABLE TABLE 
(
NUM INT NOT NULL IDENTITY,
ID INT NOT NULL
)
AS
BEGIN
DECLARE @NEXTSTRING AS NVARCHAR(MAX);
DECLARE @POS AS INT;
DECLARE @STRING AS NVARCHAR(MAX);
DECLARE @DELIMITER AS NVARCHAR(MAX);
SET @STRING = @PARAM_IDS;
SET @DELIMITER = @PARAM_DELIMITER;
SET @STRING = @STRING + @DELIMITER;
SET @POS = CHARINDEX(@DELIMITER,@STRING);

WHILE (@POS <> 0)
BEGIN
    SET @NEXTSTRING = SUBSTRING(@STRING,1,@POS - 1);
    INSERT @NEW_TABLE (ID) VALUES (@NEXTSTRING);
    SET @STRING = SUBSTRING(@STRING,@POS+1,len(@STRING));
    SET @POS = CHARINDEX(@DELIMITER,@STRING);
END 
    RETURN
END

then example of use

然后使用的例子

SET @DETAILS_COUNT = (SELECT COUNT(*) FROM delimiter(@PARAM_MS_UNIT_ID, @DELIMITER));