Vous avez besoin d'un moyen de diviser et de traiter la chaîne dans TSQL, il existe de nombreuses façons de le faire. Cet article couvre les avantages et les inconvénients de presque toutes les méthodes :
Tableaux et listes dans SQL Server 2005 et au-delà
Vous devez créer une fonction de fractionnement. Voici comment une fonction de fractionnement peut être utilisée :
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
Je préfère l'approche de la table numérique pour diviser une chaîne dans TSQL - Utilisation d'un Tableau des nombres mais il existe de nombreuses façons de diviser des chaînes dans SQL Server, voir le lien précédent, qui explique les avantages et les inconvénients de chacun.
Pour que la méthode de la table des nombres fonctionne, vous devez effectuer cette configuration de table de temps unique, ce qui créera une table Numbers
qui contient des lignes de 1 à 10 000 :
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
Une fois la table Numbers configurée, créez cette fonction de fractionnement :
CREATE FUNCTION inline_split_me (@SplitOn char(1),@param varchar(7998)) RETURNS TABLE AS
RETURN(SELECT substring(@SplitOn + @param + ',', Number + 1,
charindex(@SplitOn, @SplitOn + @param + @SplitOn, Number + 1) - Number - 1)
AS Value
FROM Numbers
WHERE Number <= len(@SplitOn + @param + @SplitOn) - 1
AND substring(@SplitOn + @param + @SplitOn, Number, 1) = @SplitOn)
GO
Vous pouvez maintenant facilement diviser une chaîne CSV en une table et la joindre :
select * from dbo.inline_split_me(';','1;22;333;4444;;') where LEN(Value)>0
SORTIE :
Value
----------------------
1
22
333
4444
(4 row(s) affected)
pour créer une nouvelle table, utilisez ceci :
--set up tables:
DECLARE @Documents table (DocumentID varchar(500), SomeValue varchar(5))
INSERT @Documents VALUES ('1,2,3,4','AAA')
INSERT @Documents VALUES ('5,6' ,'BBBB')
DECLARE @NewDocuments table (DocumentID int, SomeValue varchar(5))
--populate NewDocuments
INSERT @NewDocuments
(DocumentID, SomeValue)
SELECT
c.value,a.SomeValue
FROM @Documents a
CROSS APPLY dbo.inline_split_me(',',a.DocumentID) c
--show NewDocuments contents:
select * from @NewDocuments
SORTIE :
DocumentID SomeValue
----------- ---------
1 AAA
2 AAA
3 AAA
4 AAA
5 BBBB
6 BBBB
(6 row(s) affected)
si vous ne souhaitez pas créer de table Numbers et que vous exécutez SQL Server 2005 et versions ultérieures, vous pouvez simplement utiliser cette fonction de fractionnement (aucune table Numbers requise) :
CREATE FUNCTION inline_split_me (@SplitOn char(1),@String varchar(7998))
RETURNS TABLE AS
RETURN (WITH SplitSting AS
(SELECT
LEFT(@String,CHARINDEX(@SplitOn,@String)-1) AS Part
,RIGHT(@String,LEN(@String)-CHARINDEX(@SplitOn,@String)) AS Remainder
WHERE @String IS NOT NULL AND CHARINDEX(@SplitOn,@String)>0
UNION ALL
SELECT
LEFT(Remainder,CHARINDEX(@SplitOn,Remainder)-1)
,RIGHT(Remainder,LEN(Remainder)-CHARINDEX(@SplitOn,Remainder))
FROM SplitSting
WHERE Remainder IS NOT NULL AND CHARINDEX(@SplitOn,Remainder)>0
UNION ALL
SELECT
Remainder,null
FROM SplitSting
WHERE Remainder IS NOT NULL AND CHARINDEX(@SplitOn,Remainder)=0
)
SELECT Part FROM SplitSting
)
GO