SQL переменная длина подстроки сервера - цифры различной длины без единого шаблона - PullRequest
1 голос
/ 14 января 2020

Я проверил здесь много потоков, связанных с подстрокой переменной длины - ни один не ответил на мой конкретный c случай - пожалуйста, не отмечайте как возможный дубликат, если я как-то его не пропустил.

Azure SQL Сервер 2017

У меня есть поле varchar(50) с именем Name в таблице dbo.MyTable со следующими значениями:

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, чтобы добиться извлечения чисел?

Ответы [ 4 ]

2 голосов
/ 14 января 2020

Вы можете использовать функции 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

1 голос
/ 14 января 2020

Вот альтернатива скалярной функции. Это превзойдет скалярную функцию на дрожжах.

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
1 голос
/ 14 января 2020

Не очень приятно, но если вам действительно нужен однострочный:

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)
1 голос
/ 14 января 2020

Вы можете создать функцию, подобную этой, чтобы получить число из строки в 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;

Здесь приведено демо .

...