Fractionner le paramètre varchar séparé par une virgule en table temporaire

J'ai la procédure stockée suivante:

CREATE PROCEDURE myProc @nameList varchar(500) AS BEGIN create table #names (Name varchar(20)) -- split @nameList up into #names table END GO 

@nameList ressemblerait à ceci:

 'John, Samantha, Bob, Tom' 

utilisez convert to XML et cross apply :

  DECLARE @str varchar(50) SET @str='John, Samantha, Bob, Tom' SELECT names = yivalue('(./text())[1]', 'nvarchar(1000)') FROM ( SELECT n = CONVERT(XML, '<i>' + REPLACE(@str, ',' , '</i><i>') + '</i>') ) AS a CROSS APPLY n.nodes('i') AS y(i) 

SORTIE:

 names ----- John Samantha Bob Tom 

EDIT: ce n'est pas nécessaire à la table temporaire à l'intérieur du proc donc le proc sera:

 CREATE PROCEDURE myProc (@nameList varchar(500)) AS BEGIN SELECT names = yivalue('(./text())[1]', 'nvarchar(1000)') FROM ( SELECT n = CONVERT(XML, '<i>' + REPLACE(@nameList, ',' , '</i><i>') + '</i>') ) AS a CROSS APPLY n.nodes('i') AS y(i) END 

mais si vous voulez l'insert dans une table temporaire, voici un exemple:

 create table #names ( Name varchar(20) ) DECLARE @str varchar(50) SET @str='John, Samantha, Bob, Tom' insert into #names SELECT names = yivalue('(./text())[1]', 'nvarchar(1000)') FROM ( SELECT n = CONVERT(XML, '<i>' + REPLACE(@str, ',' , '</i><i>') + '</i>') ) AS a CROSS APPLY n.nodes('i') AS y(i) select * from #names drop table #names 

EDIT 2: la string d'input peut contenir des caractères spéciaux comme '<' , '>' , etc Ce n'est pas standard pour les noms mais si la string donnée les contient vous pouvez les supprimer en utilisant la fonction replace(@str,'<','') : replace(@str,'<','')

Avec cte récursif:

 DECLARE @nameList NVARCHAR(MAX) = 'John, Samantha, Bob, Tom' SET @nameList = @nameList + ','; WITH cte AS ( SELECT SUBSTRING(@nameList, 0, CHARINDEX(',', @nameList)) AS n , CHARINDEX(',', @nameList) AS i UNION ALL SELECT SUBSTRING(@nameList, i + 2,CHARINDEX(',', @nameList, i + 2) - i - 2) , CHARINDEX(',', @nameList, i + 2) FROM cte WHERE CHARINDEX(',', @nameList, i + 2) > 0 ) SELECT n FROM cte 

Sortie:

 n John Samantha Bob Tom 

Vous pouvez créer une fonction et appeler cette fonction depuis l'endroit où vous voulez split:

 create FUNCTION [dbo].[SplitSsortingngs](@nameList varchar(MAX), @Delimiter char(1)) returns @temptable TABLE (names varchar(MAX)) as begin declare @id int declare @x varchar(8000) select @id = 1 if len(@nameList)<1 or @nameList is null return while @id!= 0 begin set @id = charindex(@Delimiter,@nameList) if @id!=0 set @x = left(@nameList,@id - 1) else set @x = @nameList if(len(@x)>0) insert into @temptable(names) values(@x) set @Ssortingng = right(@nameList,len(@nameList) - @id) if len(@nameList) = 0 break end return end; 
 CREATE FUNCTION [dbo].[Split] ( @RowData nvarchar(MAX), @SplitOn nvarchar(5) ) RETURNS @RtnValue table ( Id int identity(1,1), Data nvarchar(100) ) AS BEGIN Declare @Cnt int Set @Cnt = 1 While (Charindex(@SplitOn,@RowData)>0) Begin Insert Into @RtnValue (data) Select Data = lsortingm(rsortingm(Subssortingng(@RowData,1,Charindex(@SplitOn,@RowData)-1))) Set @RowData = Subssortingng(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData)) Set @Cnt = @Cnt + 1 End Insert Into @RtnValue (data) Select Data = lsortingm(rsortingm(@RowData)) Return END