SQL Server字符串列表解析:现有自定义函数是否有更高效替代方案?
更高效的多值字符串解析方案
嘿,我注意到你目前在用自定义循环函数来拆分多值字符串,这种逐行循环的方式在数据量较大时性能确实会比较拉胯。下面给你几个SQL Server里更高效的替代方案,根据你的版本和需求来选:
1. 优先使用内置的STRING_SPLIT函数(SQL Server 2016+)
这是微软官方提供的内置拆分函数,性能最优,用法也最简单。直接替换你的自定义函数调用即可:
SELECT * FROM STRING_SPLIT('1,3,2,46,Mums the Order,bb', ',')
注意:如果你的SQL Server版本低于2016,这个函数不可用;另外该函数默认会过滤空值,如果需要保留空拆分结果,可以加上STRING_SPLIT(@string, @separator, 1)(SQL Server 2022+支持第三个参数)。
2. 灵活的OPENJSON方案(SQL Server 2016+)
如果你需要额外的信息(比如拆分后值的顺序索引),或者要处理一些特殊场景,OPENJSON是个不错的选择:
SELECT [value] FROM OPENJSON( CONCAT('["', REPLACE('1,3,2,46,Mums the Order,bb', ',', '","'), '"]') )
这个方法本质是把字符串转成JSON数组再解析,还能拿到每个值的序号(加上[key]列即可),适合需要保留拆分顺序的场景。
3. 兼容低版本的高效CTE拆分函数(SQL Server 2008+)
如果你的SQL Server版本比较老(比如2008或2012),没法用内置函数,可以试试基于递归CTE的集合式拆分函数,比你当前的WHILE循环高效得多:
CREATE FUNCTION dbo.fn_StringSplit_Improved ( @String NVARCHAR(4000), @Separator NVARCHAR(50) ) RETURNS TABLE AS RETURN ( WITH SplitCTE AS ( SELECT 1 AS StartPos, CHARINDEX(@Separator, @String) AS EndPos WHERE LTRIM(RTRIM(@String)) <> '' UNION ALL SELECT EndPos + LEN(@Separator), CHARINDEX(@Separator, @String, EndPos + LEN(@Separator)) FROM SplitCTE WHERE EndPos > 0 ) SELECT LTRIM(RTRIM(SUBSTRING( @String, StartPos, CASE WHEN EndPos = 0 THEN LEN(@String) - StartPos + 1 ELSE EndPos - StartPos END ))) AS value FROM SplitCTE )
调用方式和你原来的函数一致:
SELECT * FROM dbo.fn_StringSplit_Improved('1,3,2,46,Mums the Order,bb', ',')
为什么你的原函数效率低?
你当前的函数用了WHILE循环逐行插入表变量,属于**RBAR(Row-By-Agonizing-Row)**操作——也就是逐行处理数据,这种方式在数据量大时性能会急剧下降。而上面的方案都是基于集合操作的,SQL Server对集合操作的优化远优于逐行循环。
内容的提问来源于stack exchange,提问作者robinhood1995
相关产品推荐
相关产品推荐

