您可以使用 XML 并按位置抓取元素:
DECLARE @YourString VARCHAR(100)='First Second Third Fourth Fifth';
WITH StringAsXML AS
(
SELECT CAST('<x>' + REPLACE((SELECT @YourString AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML) TheXml
)
SELECT TheXml.value('x[1]/text()[1]','nvarchar(max)') AS FirstElement
,TheXml.value('x[2]/text()[1]','nvarchar(max)') AS SecondElement
,TheXml.value('x[3]/text()[1]','nvarchar(max)') AS ThirdElement
,TheXml.value('x[4]/text()[1]','nvarchar(max)') AS FourthElement
,TheXml.value('x[5]/text()[1]','nvarchar(max)') AS FifthElement
FROM StringAsXML;
备注
您可以使用PIVOT、条件聚合、FROM(VALUES()) 或以上。但是这些方法中的任何一种都需要一组已知的列(已知的元素数量或至少最大数量的元素)。
如果你不能依赖这样的知识,你可以使用动态创建的SQL。这意味着在字符串基础上创建一个工作语句并使用EXEC 进行动态执行。
更新:动态方法
这种方法将处理可变数量的元素
DECLARE @YourString VARCHAR(100)='First Second Third Fourth Fifth';
DECLARE @Delimiter CHAR(1)=' ';
DECLARE @countElements INT = LEN(@YourString)-LEN(REPLACE(@YourString,@Delimiter,''));
DECLARE @Statement VARCHAR(MAX)=
'WITH StringAsXML AS
(
SELECT CAST(''<x>'' + REPLACE((SELECT ''ReplaceYourString'' AS [*] FOR XML PATH('''')),'' '',''</x><x>'') + ''</x>'' AS XML) TheXml
)
SELECT ReplaceColumnList
FROM StringAsXML;';
DECLARE @columnList VARCHAR(MAX);
WITH cte AS
(
SELECT 1 AS ElementCounter
,CAST('TheXml.value(''x[1]/text()[1]'',''nvarchar(max)'') AS Element_01' AS VARCHAR(MAX)) AS ColStatement
UNION ALL
SELECT cte.ElementCounter+1
,cte.ColStatement + CAST(',TheXml.value(''x[' + CAST(cte.ElementCounter+1 AS VARCHAR(10)) + ']/text()[1]'',''nvarchar(max)'') AS Element_' + REPLACE(STR(cte.ElementCounter + 1,2),' ','0') AS VARCHAR(MAX))
FROM cte
WHERE cte.ElementCounter <= @countElements
)
SELECT @columnList=(SELECT TOP 1 cte.ColStatement FROM cte ORDER BY cte.ElementCounter DESC)
--replace the string you want to split
SET @Statement = REPLACE(@Statement,'ReplaceYourString',@YourString);
--replace the columnList
SET @Statement = REPLACE(@Statement,'ReplaceColumnList',@columnList);
EXEC(@Statement);
更新 2:我所知道的最小的完全内联和 位置安全 拆分器
试试这个:
DECLARE @inp VARCHAR(200) = 'First Second Third Fourth Fifth';
DECLARE @dlmt VARCHAR(100)=' ';
;WITH
a AS (SELECT n=0, i=-1, j=0 UNION ALL SELECT n+1, j, CHARINDEX(@dlmt, @inp, j+1) FROM a WHERE j > i),
b AS (SELECT n, SUBSTRING(@inp, i+1, IIF(j>0, j, LEN(@inp)+1)-i-1) s FROM a WHERE i >= 0)
SELECT * FROM b;
为了完成它:上面的小分离器结合PIVOT:
;WITH
a AS (SELECT n=0, i=-1, j=0 UNION ALL SELECT n+1, j, CHARINDEX(@dlmt, @inp, j+1) FROM a WHERE j > i),
b AS (SELECT n, SUBSTRING(@inp, i+1, IIF(j>0, j, LEN(@inp)+1)-i-1) s FROM a WHERE i >= 0)
SELECT p.*
FROM b
PIVOT(MAX(s) FOR n IN([1],[2],[3],[4],[5])) p;