SQL Server动态截取指定分隔符第N次位置对应子串的实现方法
SQL Server 动态截取指定分隔符第N段子串实现
你之前使用单次CHARINDEX配合SUBSTRING的写法,只能定位分隔符第一次出现的位置,自然只能返回首段内容。下面给出两种无静态函数依赖、支持动态传入位置参数(1-15)的实现方案,自动适配-/_/~三种分隔符,完全匹配你给出的示例效果。
方案1:适用于SQL Server 2022及以上版本(性能最优)
SQL Server 2022版本的STRING_SPLIT函数支持开启序号返回参数,直接匹配传入的位置参数即可,写法最简洁,执行效率最高。
-- 参数说明:@inputStr 绑定表中nvarchar类型字段,@pos 绑定C#表单传入的1-15位置参数 DECLARE @inputStr NVARCHAR(MAX) = 'HGHGSD_JHJSD_HGSDHGJD_GFSDGFSHDGF_GFSD'; DECLARE @pos INT = 3; -- 自动识别当前字符串使用的分隔符 DECLARE @delimiter NCHAR(1) = ( SELECT TOP 1 d FROM (VALUES ('-'),('_'),('~')) t(d) WHERE CHARINDEX(d, @inputStr) > 0 ); SELECT value AS Result FROM STRING_SPLIT(@inputStr, @delimiter, 1) WHERE ordinal = @pos + 1;
效果验证(和需求示例完全一致):
- @pos=1时返回
JHJSD - @pos=2时返回
HGSDHGJD - @pos=3时返回
GFSDGFSHDGF
如果业务场景中每个字段使用的分隔符固定,可以去掉自动识别分隔符的逻辑,直接给@delimiter赋值固定分隔符,性能会进一步提升。
方案2:适用于SQL Server 2019及以下低版本
如果你的数据库版本低于2022,可以用递归CTE逐段定位分隔符位置,同样不需要提前创建持久化自定义函数,支持动态传参:
DECLARE @inputStr NVARCHAR(MAX) = 'hwerweyri~sdjhfkjhsdkjfhds~jsdfhjsdhf~mdnfsd,mfn'; DECLARE @pos INT = 2; DECLARE @delimiter NCHAR(1) = ( SELECT TOP 1 d FROM (VALUES ('-'),('_'),('~')) t(d) WHERE CHARINDEX(d, @inputStr) > 0 ); WITH SplitCTE AS ( SELECT 1 AS seg_index, 1 AS start_pos, CHARINDEX(@delimiter, @inputStr) AS delimiter_pos UNION ALL SELECT seg_index + 1, delimiter_pos + 1, CHARINDEX(@delimiter, @inputStr, delimiter_pos + 1) FROM SplitCTE WHERE delimiter_pos > 0 AND seg_index <= @pos ) SELECT CASE WHEN delimiter_pos > 0 THEN SUBSTRING(@inputStr, start_pos, delimiter_pos - start_pos) ELSE SUBSTRING(@inputStr, start_pos, LEN(@inputStr) - start_pos + 1) END AS Result FROM SplitCTE WHERE seg_index = @pos + 1 OPTION (MAXRECURSION 16); -- 最大支持传入位置15,设置16足够覆盖无溢出风险
效果验证:上述示例串传入@pos=2时,返回第二个~之后的子串jsdfhjsdhf,符合预期。
程序对接说明
直接把上述逻辑写成参数化SQL即可,不需要在数据库中创建静态自定义函数:
@inputStr参数绑定对应表的nvarchar类型字段@pos参数绑定C#表单传入的1-15的数值- 两种方案的执行效率都可以满足生产环境常规查询需求,因为最大拆分深度只有16层,不会出现性能问题。
- 如果传入的位置超过字符串实际分隔的段数,代码默认返回最后一段到字符串末尾的内容,可以根据业务需要调整为空值等其他返回规则。
内容的提问来源于stack exchange,提问作者choongmoongchool
相关产品推荐
相关产品推荐

