SSMS 2016 中的正则表达式

Regex in SSMS 2016

提问人:Andrzej Lisowski 提问时间:10/12/2023 更新时间:10/13/2023 访问量:43

问:

我正在使用 ssms 2016。我有以下模式的字符串,我需要从中提取两件事。14Jan22_B_15May23_15_N_323_412_102

  1. 两个之间的第一个数字。在本例中,它是 15,但可以是任何数字。我尝试了以下方法,但没有用。它返回 0_
DECLARE @InputString VARCHAR(MAX) = '14Jan22_B_15May23_15_N_323_412_102'; 
DECLARE @MatchPos INT = PATINDEX('%_[0-9]+_%', @InputString);
select @MatchPos
  1. 或 之后的所有数字。此外,这或需要从第 1 点开始在数字之后。因为字母 B 也可以是字母 N。_N__R__N__R_

我没有开始处理第 2 点,因为我不知道如何解决第 1 点

正则表达式 T-SQL SSMS SSMS-2016

评论

0赞 Thom A 10/12/2023
SSMS 在其查找和替换功能中支持正则表达式,但仅此而已。不过,你似乎不是在这里询问 SSMS,而是 T-SQL/SQL Server;SQL Server 不支持正则表达式。SSMS 只是一个类似 IDE 的应用程序,可与多种产品一起使用,例如(但不限于)SQL Server、Azure SQL Edge 和 Azure Synapse。SSMS 可能与此处的问题无关。您实际使用什么产品作为数据引擎?为数据引擎标记 [ssms] 就像为编程语言标记 [visual-studio] 一样;它实际上并没有真正告诉我们任何事情。
0赞 Thom A 10/12/2023
'%_[0-9]+_%'在 T-SQL 的基本模式匹配中,是指:0+ 个字符 () 后跟任意字符 (),后跟任意数字字符 (),后跟加号字符 (),后跟任意字符 (),后跟 0+ 个字符 ()。由于字符串中没有加号 () 字符,因此找不到任何模式。%_[0-9]+_%+
0赞 Andrzej Lisowski 10/12/2023
@ThomA 有没有办法定义“_之间的任意数字”的模式?
0赞 Andrew 10/12/2023
您可以尝试使用 string_split 将该字符串拆分为行,然后在其输出上进行数字处理?
0赞 Thom A 10/12/2023
TRY_CONVERT@Andrew,这比那个可怕的功能更有意义。intISNUMERIC

答:

0赞 GlockByte 10/13/2023 #1

您的尝试中有一些错误,您可能无法立即发现。其中一个问题是 in 是单个字符的通配符。第二个问题是 ,不是 0 到 9 之间的数字,您可以在其中搜索一个数字的单个字符。'_''%_[0-9]+_%'15[0-9]

也许不是最干净的,但它有效:

DECLARE @InputString VARCHAR(MAX) = '14Jan22_B_15May23_15_N_323_412_102'; 
DECLARE @MatchPos int = ISNULL(NULLIF(PATINDEX('%[_][0-9][_]%', @InputString),0),PATINDEX('%[_][0-9][0-9][_]%', @InputString))
DECLARE @num int = CHARINDEX('_N_',@InputString,@MatchPos)+3
DECLARE @t nvarchar(MAX) = SUBSTRING(@InputString,@num,LEN(@inputString)-@num)

;WITH CTE AS (
    SELECT 
        REPLACE(LEFT(@t,CHARINDEX('_',@t)),'_','') [NUMBER], 
        CONCAT(REPLACE(@t,LEFT(@t,CHARINDEX('_',@t)),''),'_') [REMAINDER],  
        @t AS [Original Number After @num]
    UNION ALL
    SELECT 
        REPLACE(LEFT([REMAINDER],CHARINDEX('_',[REMAINDER])),'_',''), 
        REPLACE([REMAINDER],LEFT([REMAINDER],CHARINDEX('_',[REMAINDER])),''), 
        @t
    FROM CTE 
    WHERE LEN([REMAINDER])>0
)
SELECT NUMBER AS [Ending Numbers] from CTE
SELECT @MatchPos [MatchPos index], REPLACE(substring(@InputString,@MatchPos,3),'_','') AS [MatchPos Number], @num [_N_ INDEX], SUBSTRING(@InputString,@num,LEN(@inputString)-@num) AS [Numbers After _N_]