SQL Server中拆分表字符串字段生成双列结果的技术问询
在SQL Server中拆分字符串字段的解决方案
针对你需要把table1中field1字段的字符串(格式如s1,t1、1,a、2,b、3,c、4,d)拆分成两列表格的需求,我整理了几个适配不同SQL Server版本的实用方案:
方案一:适用于SQL Server 2022及以上版本
SQL Server 2022新增了STRING_SPLIT的ordinal参数,能可靠保留拆分后的顺序,这是最简洁的实现方式:
WITH SplitRows AS ( -- 按中文顿号拆分整个字符串,同时获取拆分后的顺序序号 SELECT value, ordinal FROM STRING_SPLIT((SELECT field1 FROM table1), '、', 1) ), DataRows AS ( -- 跳过第一行的列名,将每一行按英文逗号拆分为两列 SELECT LEFT(value, CHARINDEX(',', value) - 1) AS s1, RIGHT(value, LEN(value) - CHARINDEX(',', value)) AS t1 FROM SplitRows WHERE ordinal > 1 ) SELECT s1, t1 FROM DataRows;
方案二:适用于SQL Server 2016-2019版本
这些版本没有ordinal参数,我们可以用ROW_NUMBER()来模拟顺序(注:这种排序在绝大多数场景下能保持原顺序,若需绝对可靠可改用方案三):
WITH SplitRows AS ( SELECT value, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn FROM STRING_SPLIT((SELECT field1 FROM table1), '、') ), DataRows AS ( SELECT LEFT(value, CHARINDEX(',', value) - 1) AS s1, RIGHT(value, LEN(value) - CHARINDEX(',', value)) AS t1 FROM SplitRows WHERE rn > 1 ) SELECT s1, t1 FROM DataRows;
方案三:适用于SQL Server 2008及以上老版本
如果你的版本不支持STRING_SPLIT,可以先创建一个自定义拆分函数,再进行处理:
第一步:创建自定义拆分函数
CREATE FUNCTION dbo.SplitString ( @InputString NVARCHAR(MAX), @Delimiter NVARCHAR(50) ) RETURNS @OutputTable TABLE ( Item NVARCHAR(MAX), Ordinal INT ) AS BEGIN DECLARE @StartIndex INT, @EndIndex INT, @Ordinal INT = 1 SET @StartIndex = 1 -- 确保字符串末尾有分隔符,避免遗漏最后一个元素 IF SUBSTRING(@InputString, LEN(@InputString) - LEN(@Delimiter) + 1, LEN(@Delimiter)) <> @Delimiter BEGIN SET @InputString = @InputString + @Delimiter END WHILE CHARINDEX(@Delimiter, @InputString) > 0 BEGIN SET @EndIndex = CHARINDEX(@Delimiter, @InputString) INSERT INTO @OutputTable(Item, Ordinal) SELECT SUBSTRING(@InputString, @StartIndex, @EndIndex - @StartIndex), @Ordinal SET @InputString = SUBSTRING(@InputString, @EndIndex + LEN(@Delimiter), LEN(@InputString)) SET @Ordinal = @Ordinal + 1 END RETURN END GO
第二步:使用函数拆分字段
WITH SplitRows AS ( SELECT Item AS value, Ordinal FROM dbo.SplitString((SELECT field1 FROM table1), '、') ), DataRows AS ( SELECT LEFT(value, CHARINDEX(',', value) - 1) AS s1, RIGHT(value, LEN(value) - CHARINDEX(',', value)) AS t1 FROM SplitRows WHERE Ordinal > 1 ) SELECT s1, t1 FROM DataRows;
额外说明
- 如果你的字符串中可能存在嵌套逗号(比如某行是
1,a,b),上述方法会失效,这种情况需要用更复杂的解析逻辑(比如基于XML或JSON的方式); - 如果需要动态将第一行的
s1,t1作为列名(而不是硬编码),可以结合动态SQL实现,有需要的话可以再补充这部分代码。
内容的提问来源于stack exchange,提问作者user9706045
相关产品推荐
相关产品推荐

