sql - 如何在 SQL 函数 CHARINDEX 中使用 RegEx 查找第 n 次出现

标签 sql sql-server regex sql-server-2014 charindex

以下算法的目的是从 key 中提取某些字段集(在本示例中,提取前 2 个字段),并且它有效。这些字段由冒号分隔:

declare @key nvarchar (max);
declare @pos int;
declare @fields nvarchar (max);

set @key = 'Field-1:Field-2:Field-3:Field-4:Field-5';
set @pos = charindex(':', @key, charindex (':', @key) + 1);
set @fields = left(@key, @pos - 1);

select @fields;

结果:字段 1:字段 2

Microsoft document说第一个参数是一个表达式,但我认为在 CHARINDEX 上下文中他们的意思是,这个表达式应该计算为字符串文字;因此,以下尝试通过正则表达式来获取第二次出现的情况不起作用;显然要么它不受支持,要么我使用了错误的语法:

--match the second occurrence of the delimiter using RegEx
set @pos = charindex (':.*?(:)', @key);

换句话说,是否可以使用 RegEx 找到给定文本中第 n 次出现的分隔符的位置,以便我可以避免多个嵌套的 CHARINDEX 或循环解析?撇开不谈,如果 n 作为参数传递,那么我什至不能再使用静态嵌套......

预先感谢您的帮助。

环境:Microsoft SQL Server 2014 (SP3) 标准版(64 位)

最佳答案

提取字符串的第 n 个子字符串没有简单的方法,只有技巧。以下是基于集合的递归 CTE 方法:

DECLARE @str NVARCHAR(MAX) = N'Field-1:Field-2:Field-3:Field-4:Field-5';
DECLARE @num INT = 4;

WITH rcte AS (
    SELECT str = @str
         , n = 1
         , p = CHARINDEX(':', @str, 1)
    UNION ALL
    SELECT str
         , n + 1
         , CHARINDEX(':', str, p + 1)
    FROM rcte
    WHERE n < @num AND p > 0
)
SELECT CASE WHEN p > 0 THEN SUBSTRING(str, 1, p - 1) ELSE str END
FROM rcte
WHERE n = @num;

如果循环是一个选项,那么:

DECLARE @str NVARCHAR(MAX) = N'Field-1:Field-2:Field-3:Field-4:Field-5';
DECLARE @num INT = 4;
DECLARE @n INT = 0;
DECLARE @p INT = 0;

WHILE 1 = 1
BEGIN
    SET @n = @n + 1;
    SET @p = CHARINDEX(':', @str, @p + 1);
    IF @n = @num OR @p = 0 BREAK;
END;

SELECT CASE WHEN @p > 0 THEN SUBSTRING(@str, 1, @p - 1) ELSE @str END;

DB<>Fiddle

关于sql - 如何在 SQL 函数 CHARINDEX 中使用 RegEx 查找第 n 次出现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57715991/

相关文章:

sql - 在层次结构中查找最新对象,其中最新对象未标记为已删除

sql - 在 Oracle 中使用 to_date 的查询在 Windows 和 Ubuntu IDE 中运行不同

sql-server - WPA 看不到 ETW 事件数据,而 tracerpt 可以

sql-server - 是否有免费的 Web UI 可以绑定(bind)到 sql server 数据库并允许基本的列过滤和数据导出?

c# - 从 SQL Server 数据库填充 DataTable

python - 匹配 Python 字典中的不完整字符串

python - 为什么 findall 返回空字符串?

sql - 如何在 Sybase sql 子查询的结果上正确使用 GROUP BY

java - 在 Java 上连接的 Oracle 数据库中执行存储过程

python - 在python中使用正则表达式返回特定单词之间的大写单词