如何查找并显示 SQL Server 字符串中某个模式的所有实例?

问题描述 投票:0回答:4

所以我正在尝试编写一个 UDF 来从字符串中提取特定数据。

  'random text here Task 1234 blah blah more text task 4567'

我想提取“任务1234和任务4567”并让它们像这样显示

  'Task 1234, task 4567'

这是我到目前为止所得到的,但似乎只能完成第一个任务或第二个任务,但不能同时完成两个任务。

Alter Function [dbo].[fn_GetTask](@strText VARCHAR(MAX))
RETURNS varchar(1000)
AS
BEGIN
  while patindex('%Task%', @strText) > 0

BEGIN
    SET @strText = substring(@strText, (CHARINDEX(substring(@strText, Patindex('%Task%', @strText) +4, 5), @strText, 5)),5)
    end
RETURN @strText

END

这是非常漫长的一天。我觉得我在这里缺少一些非常基本的东西。

sql-server substring udf patindex
4个回答
3
投票
ALTER Function [dbo].[fn_GetTask](@strText VARCHAR(MAX))
RETURNS varchar(1000)
AS
BEGIN

    DECLARE @ReturnString VARCHAR(1000) = ''

    WHILE PATINDEX('%Task%', @strText) > 0

    BEGIN

       DECLARE @FoundString VARCHAR(1000) = SUBSTRING(@strText,PATINDEX('%Task%',@strText),9)

       IF (LEN(@ReturnString) > 0)
       BEGIN
          SET @ReturnString += ', '
       END

       SET @ReturnString += @FoundString

       SET @strText = RIGHT(@strText,LEN(@strText) - PATINDEX('%' + @FoundString + '%',@StrText))
    END

    RETURN @ReturnString

END

正如我在 while 循环期间提到的那样,您在写入字符串时使用结果字符串进行搜索。你没有一种机制来修剪原始字符串或跟踪你的进度,这是一种方法,我使用了额外的变量,这样我就不必多次嵌套相同的语句。


3
投票

如果您需要更多基于SET的解决方案,可以通过以下方式搜索:

DECLARE @pattern nvarchar(MAX) = N'%task [0-9][0-9][0-9][0-9]%';
DECLARE @input nvarchar(MAX) = N'random text here Task 1212 blah blah more text task 4567';
WITH Src AS
(
    SELECT
        SUBSTRING(@input, PATINDEX(@pattern, @input), 9) Val,
        STUFF(@input, 1, PATINDEX(@pattern, @input)+9, '') Txt
        WHERE PATINDEX(@pattern, @input)>0
    UNION ALL
    SELECT
        SUBSTRING(Txt, PATINDEX(@pattern, Txt), 9),
        STUFF(Txt, 1, PATINDEX(@pattern, Txt)+9, '')
    FROM Src
    WHERE PATINDEX(@pattern, Txt)>0
)
SELECT STUFF((SELECT ', '+Val FROM Src FOR XML PATH('')), 1, 2, '')

0
投票

使用下面的代码并转换为函数

declare @str varchar(100)='random text here Task 1234 blah blah more text task 4567 random task 9556'
declare @gstr varchar(100)=''--for saving the output string
declare @flag int=1--to identify the pattern starting
declare @move int=1-- change start of the string 
 while  PATINDEX('%Task%', substring(@str,@move,LEN(@str)))>0
begin
set @str=substring(@str,@move,LEN(@str))
set @flag= PATINDEX('%Task%', @str)
set @gstr= @gstr+','+SUBSTRING(@str, @flag,9)
set @move=@flag+9
end
select STUFF(@gstr,1,1,'')

0
投票

我目前使用的是这样的:

DECLARE @str VARCHAR(3000) = '123456##78987##654321qwertyuiopasdfghjkl##zxcvbnm'
DECLARE @pat VARCHAR(3000) = '%##%'

;WITH cte AS (
    SELECT
        @str AS substr, --debug
        PATINDEX(@pat, @str) AS substrixfound, 
        0 AS pastindexfound
    UNION ALL
    SELECT 
        SUBSTRING(cte.substr, cte.substrixfound + 1, LEN(@str)), 
        PATINDEX(@pat, SUBSTRING(cte.substr, cte.substrixfound + 1, LEN(@str))) ,
        cte.pastindexfound + cte.substrixfound
    FROM cte WHERE cte.substrixfound > 0
)
SELECT *, SUBSTRING(@str, pastindexfound, LEN(@str)) AS test
FROM cte 
WHERE cte.pastindexfound > 0

在性能方面可能会更好,但我比其他解决方案更喜欢,因为它给出了在单个查询中找到的索引,而不是使用循环。

© www.soinside.com 2019 - 2024. All rights reserved.