SQL Server 2016+:查找不在单引号或方括号内的首个", --"位置
解法:仅用SELECT语句查找目标位置
可以通过递归CTE遍历字符串状态,结合字符位置匹配来实现需求,具体SQL如下:
WITH StringCTE AS ( -- 初始化:处理第一个字符的状态 SELECT string, desired_pos, 1 AS pos, SUBSTRING(string, 1, 1) AS curr_char, CASE WHEN SUBSTRING(string, 1, 1) = '''' THEN 1 ELSE 0 END AS in_quote, CASE WHEN SUBSTRING(string, 1, 1) = '[' THEN 1 ELSE 0 END AS in_bracket, SUBSTRING(string, 1, 1) AS prev_char FROM (VALUES (N'''a, --''[, --], --[, --]', 14), (N'[a, --b]aaaaaaa_ , --'', --''', 18) ) t(string, desired_pos) UNION ALL -- 递归遍历后续每个字符,更新状态 SELECT s.string, s.desired_pos, s.pos + 1 AS pos, SUBSTRING(s.string, s.pos + 1, 1) AS curr_char, -- 处理单引号状态:仅非连续单引号才切换状态(连续''视为转义) CASE WHEN s.in_quote = 1 THEN CASE WHEN SUBSTRING(s.string, s.pos + 1, 1) = '''' AND s.prev_char <> '''' THEN 0 ELSE 1 END ELSE CASE WHEN SUBSTRING(s.string, s.pos + 1, 1) = '''' AND s.prev_char <> '''' THEN 1 ELSE 0 END END AS in_quote, -- 处理方括号状态:遇到[进入,遇到]退出 CASE WHEN s.in_bracket = 1 THEN CASE WHEN SUBSTRING(s.string, s.pos + 1, 1) = ']' THEN 0 ELSE 1 END ELSE CASE WHEN SUBSTRING(s.string, s.pos + 1, 1) = '[' THEN 1 ELSE 0 END END AS in_bracket, SUBSTRING(s.string, s.pos + 1, 1) AS prev_char FROM StringCTE s WHERE s.pos < LEN(s.string) ), DashPositions AS ( -- 递归找出所有`, --`的起始位置 SELECT string, desired_pos, CHARINDEX(', --', string, 1) AS dash_pos FROM (VALUES (N'''a, --''[, --], --[, --]', 14), (N'[a, --b]aaaaaaa_ , --'', --''', 18) ) t(string, desired_pos) WHERE CHARINDEX(', --', string, 1) > 0 UNION ALL SELECT dp.string, dp.desired_pos, CHARINDEX(', --', dp.string, dp.dash_pos + 1) AS dash_pos FROM DashPositions dp WHERE CHARINDEX(', --', dp.string, dp.dash_pos + 1) > 0 ), ValidPositions AS ( -- 筛选出未被引号/方括号包裹的`, --`位置 SELECT dp.string, dp.desired_pos, dp.dash_pos FROM DashPositions dp WHERE NOT EXISTS ( SELECT 1 FROM StringCTE sc WHERE sc.string = dp.string AND sc.pos BETWEEN dp.dash_pos AND dp.dash_pos + 3 -- 覆盖`, --`的4个字符位置 AND (sc.in_quote = 1 OR sc.in_bracket = 1) ) ) -- 取每个字符串的第一个有效位置 SELECT string, desired_pos, MIN(dash_pos) AS actual_pos FROM ValidPositions GROUP BY string, desired_pos;
逻辑说明
StringCTE:逐个字符遍历字符串,跟踪当前是否处于单引号内或方括号内。单引号仅在非连续出现时切换状态(连续两个'视为转义字符,不改变状态);方括号遇到[进入包裹状态,遇到]退出。DashPositions:递归查找字符串中所有, --的起始位置。ValidPositions:检查每个, --的4个字符(逗号、空格、两个减号)是否都不在引号或方括号包裹范围内,筛选出符合条件的位置。- 最后通过
MIN(dash_pos)获取每个字符串的首个有效位置。
注意事项
- 如果字符串中不存在目标
, --,actual_pos会返回NULL,可根据需求用ISNULL处理。 - 当前逻辑未处理方括号嵌套(如
[[a,b]])的场景,若需要支持嵌套,需调整方括号的状态判断逻辑。 - 单引号转义逻辑符合SQL字符串的转义规则(连续两个
'表示一个实际的')。
内容的提问来源于stack exchange,提问作者Mike S
相关产品推荐
相关产品推荐

