Using PATINDEX to find varying length patterns in T-SQL

后端 未结 6 2112
旧时难觅i
旧时难觅i 2020-12-19 01:20

I\'m looking to pull floats out of some varchars, using PATINDEX() to spot them. I know in each varchar string, I\'m only interested in the first float that exists, but they

相关标签:
6条回答
  • 2020-12-19 02:01

    Yes you need to link to the clr to get regex support. But if PATINDEX does not do what you need then regex was designed exactly for that.

    http://msdn.microsoft.com/en-us/magazine/cc163473.aspx

    0 讨论(0)
  • 2020-12-19 02:02

    Wildcards.

    SELECT PATINDEX('%[0-9]%[0-9].[0-9]%[0-9]%','some text 456.09 other text')
    SELECT PATINDEX('%[0-9]%[0-9].[0-9]%[0-9]%','even more text 98273.453 la la la')
    
    0 讨论(0)
  • Should be checked for robustness (what if you only have an int, for example), but this is just to put you on a track:

    if exists (select routine_name from information_schema.routines where routine_name = 'GetFirstFloat')
        drop function GetFirstFloat
    go
    
    create function GetFirstFloat (@string varchar(max))
    returns float
    as
    begin
        declare @float varchar(max)
        declare @pos int
    
        select @pos = patindex('%[0-9]%', @string)
        select @float = ''
    
        while isnumeric(substring(@string, @pos, 1)) = 1
        begin
            select @float = @float + substring(@string, @pos, 1)
            select @pos = @pos + 1
        end
    
        return cast(@float as float)
    end
    go
    
    
    select dbo.GetFirstFloat('this is a string containing pi 3.14159216 and another non float 3 followed by a new fload 5.41 and that''s it')
    select dbo.GetFirstFloat('this is a string with no float')
    select dbo.GetFirstFloat('this is another string with an int 3')
    
    0 讨论(0)
  • 2020-12-19 02:05

    PATINDEX is not powerful enough to do that. You should use regular expressions.

    SQL Server has Regular expression support since SQL Server 2005.

    0 讨论(0)
  • 2020-12-19 02:15

    I blogged about this a while ago. Extracting numbers with SQL server

    Declare @Temp Table(Data VarChar(100))
    
    Insert Into @Temp Values('some text 456.09 other text')
    Insert Into @Temp Values('even more text 98273.453 la la la')
    Insert Into @Temp Values('There are no numbers in this one')
    
    Select Left(
                 SubString(Data, PatIndex('%[0-9.-]%', Data), 8000),
                 PatIndex('%[^0-9.-]%', SubString(Data, PatIndex('%[0-9.-]%', Data), 8000) + 'X')-1)
    From   @Temp
    
    0 讨论(0)
  • 2020-12-19 02:25

    Given that the pattern is going to be varied in length, you're not going to have a rough time getting this to work with PATINDEX. There is another post that I wrote, which I've modified to accomplish what you're trying to do here. Will this work for you?

    CREATE TABLE #nums (n INT)
    DECLARE @i INT 
    SET @i = 1
    WHILE @i < 8000 
    BEGIN
        INSERT #nums VALUES(@i)
        SET @i = @i + 1
    END
    
    CREATE TABLE #tmp (
      id INT IDENTITY(1,1) not null,
      words VARCHAR(MAX) null
    )
    
    INSERT INTO #tmp
    VALUES('I''m looking for a number, regardless of length, even 23.258 long'),('Maybe even pi which roughly 3.14159265358,'),('or possibly something else that isn''t a number')
    
    UPDATE #tmp SET words = REPLACE(words, ',',' ')
    
    ;WITH CTE AS (SELECT ROW_NUMBER() OVER (ORDER BY ID) AS rownum, ID, NULLIF(SUBSTRING(' ' + words + ' ' , n , CHARINDEX(' ' , ' ' + words + ' ' , n) - n) , '') AS word
        FROM #nums, #tmp
        WHERE ID <= LEN(' ' + words + ' ') AND SUBSTRING(' ' + words + ' ' , n - 1, 1) = ' ' 
        AND CHARINDEX(' ' , ' ' + words + ' ' , n) - n > 0),
        ids AS (SELECT ID, MIN(rownum) AS rownum FROM CTE WHERE ISNUMERIC(word) = 1 GROUP BY id)
    SELECT CTE.rownum, cte.id, cte.word
    FROM CTE, ids WHERE cte.id = ids.id AND cte.rownum = ids.rownum
    

    The explanation and origin of the code is covered in more detail in the origional post

    0 讨论(0)
提交回复
热议问题