SQL 服务器子字符串可变长度 - 长度不一但模式不一致的数字

SQL Server Substring variable length - numerals of varying length with no consistent pattern

我已经检查了这里与可变长度子字符串相关的许多线程 - none 已经回答了我的具体情况 - 请不要标记为可能重复,除非我不知何故错过了它。

蔚蓝 SQL 服务器 2017

我在 table dbo.MyTable 中有一个名为 Namevarchar(50) 字段,具有以下类型的值:

1143_RRF-tansTracks
DGGP-45-HAEJTJ_wer
3TTKH_YPreTTR
4534554PostRTE
WERET677ITD
PINT_pilly-er_45321

我正在尝试使用 SUBSTRING 来获得这个:

1143
45
3
4534554
677
45321

我无法理解如何定义 length 参数。

我目前拥有的:

SUBSTRING(Name, (PATINDEX('%[0-9]%',[Name])),7) AS Number

7 只是一个占位符 - 我该如何正确编写 length 参数来实现我的号码提取?

您可以创建这样的函数以从 SQL 服务器中的字符串中获取数字,如下所示。

CREATE FUNCTION dbo.udf_GetNumeric (@strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
    DECLARE @intAlpha INT

    SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)

    BEGIN
        WHILE @intAlpha > 0
        BEGIN
            SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '')
            SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
        END
    END

    RETURN ISNULL(@strAlphaNumeric, 0)
END
GO

SELECT dbo.udf_GetNumeric('1143_RRF-tansTracks') AS NumberFromString;

这是给定的 demo

您可以使用 TRANSLATE()REPLACE() 函数作为

SELECT Str,
       REPLACE(
       TRANSLATE(Str, 'abcdefghiJklmnopqrstuvwxyz_-',
                      '                            '), ' ', '')
FROM
(
  VALUES
  ('1143_RRF-tansTracks'),
  ('DGGP-45-HAEJTJ_wer'),
  ('3TTKH_YPreTTR'),
  ('4534554PostRTE'),
  ('WERET677ITD'),
  ('PINT_pilly-er_45321')
) T(Str);

Online Demo

不太好,但如果你真的需要单线:

SUBSTRING(SUBSTRING(Name, PATINDEX('%[0-9]%',Name),999),1,PATINDEX('%[^0-9]%',SUBSTRING(Name,PATINDEX('%[0-9]%',Name),999)+'x')-1)

或者:

SUBSTRING(Name,PATINDEX('%[0-9]%',Name),LEN(NAME)-PATINDEX('%[0-9]%',REVERSE(Name))-PATINDEX('%[0-9]%',Name)+2)

这是使用标量函数的替代方法。这将突飞猛进地胜过标量函数。

create function [dbo].[GetNumbersOnly](@pString varchar(8000))
returns table as return
    WITH
        E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
        E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
        E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
        cteTally(N) AS (SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4)
    , ValueList as 
    (
        SELECT N, SUBSTRING(@pString, N, 1) as NewVal
        FROM cteTally
        WHERE N <= LEN(@pString)
            AND SUBSTRING(@pString, N, 1) LIKE ('[0-9]')  
    )

    SELECT top 1 NewVal = replace(STUFF((
                   SELECT '+' + NewVal
                     FROM ValueList
                      FOR XML PATH(''), TYPE).value('.','varchar(max)'),1,1,''), '+', '')
    FROM ValueList

然后您可以将其用于当前输出。

declare @Something table
(
    Name varchar(100)
)

insert @Something values
('1143_RRF-tansTracks')
, ('DGGP-45-HAEJTJ_wer')
, ('3TTKH_YPreTTR')
, ('4534554PostRTE')
, ('WERET677ITD')
, ('PINT_pilly-er_45321')

select *
from @Something s
cross apply dbo.GetOnlyNumbers(s.Name) n