如何使用正则表达式删除 MS SQL Server Management Studio 中的数字?

How to use regular expression to remove number in MS SQL Server Management Studio?

我在 table 中有一个字段包含不同程序的不同 ID,如下所示:

ProgrammeID
-----------
Prog201604L
Prog201503L
Pro2015N
Pro2014N
Programme2010
Programme2011

每个程序ID都有其含义。字符串中间的数字表示时间或月份。很明显 Prog201604L 和 Prog201503L 表示相同的程序但在不同的年份(其余的也是如此)。我想要做的是删除数字,因此在删除之后 programmeID 将如下所示:

ProgrammeID
-----------
ProgL
ProgL
ProN
ProN
Programme
Programme

然后我可以将这些程序聚合在一起。

我目前正在使用 SSMS 2012,不确定是否有像 RegEx 这样的 sql 语句。找了很久,网上的解决方案主要是Oracle和MySQL。我发现的是 PATINDEX() ,它似乎支持正则表达式。谁能告诉我如何创建适合我情况的模式以及我应该使用什么样的语句?

提前致谢

您可以创建一个函数并将每一行的值传递给函数 作为(只是 运行 这个查询)

Create Function [dbo].[RemoveNonAlphaCharacters](@Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin

    Declare @KeepValues as varchar(50)
    Set @KeepValues = '%[^a-z]%'
    While PatIndex(@KeepValues, @Temp) > 0
        Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '')

    Return @Temp
End

---Call it like this:

Declare @tbl table (ProgrammeID varchar(20))
insert into @tbl values ('ProgL'),('ProgL'),('ProN'),('ProN'),('Programme'),('Programme')

select * from @tbl
Select dbo.RemoveNonAlphaCharacters(ProgrammeID) from @tbl

How to strip all non-alphabetic characters from string in SQL Server?

Remove numbers from string sql server

一个聪明的选择是从左侧获取 ProgrammeID 列的子字符串,直到遇到第一个数字,然后将其与右侧子字符串的反向连接,直到遇到第一个数字:

SELECT
    SUBSTRING(ProgrammeID,
              1,
              PATINDEX('%[0-9]%', ProgrammeID) - 1) +
    REVERSE(SUBSTRING(REVERSE(ProgrammeID),
              1,
              PATINDEX('%[0-9]%', REVERSE(ProgrammeID)) - 1))
FROM yourTable

我在字符串表达式中创建了一个 user-defined function for SQL Server to remove non-numeric characters

我们可以修改它以从输入字符串中删除相反的数字字符,如下所示

 while patindex('%[0-9]%', @str) > 0
  set @str = stuff(@str, patindex('%[0-9]%', @str), 1, '')
 return @str

希望对你有帮助

如果数字部分始终为 6 个字符,则可以使用以下内容。

DECLARE @ProgrammeID VARCHAR(50) = 'Prog201604L'
SELECT STUFF(@ProgrammeID, PATINDEX( '%[0-9]%', @ProgrammeID), 6, '')

如果人数不固定... 往上延伸

CREATE TABLE #Programme ( ProgrammeID VARCHAR(50) )

INSERT INTO #Programme
VALUES
    ('Prog201604L')
    ,('Pro2015N')
    ,('Programme2010')
    ,('Prog2016L')
    ,('Pro2N')
    ,('Prog')
    ,('2010')

SELECT ProgrammeID, 
    ISNULL(
            STUFF(ProgrammeID, 
                    PATINDEX( '%[0-9]%', ProgrammeID),  -- get number start index   
                    IIF(PATINDEX( '%[0-9][a-z]%',ProgrammeID)= 0, PATINDEX( '%[0-9]',ProgrammeID), PATINDEX( '%[0-9][a-z]%',ProgrammeID)) + 1   -- get the last number index 
                    - PATINDEX( '%[0-9]%', ProgrammeID),    -- get the number character length
                     '')
        ,ProgrammeID)           -- Where there are no numbers in the string you will get Null, replace it with actual string 
        AS [Without Numbers]
FROM #Programme

这将处理具有不同数字甚至没有数字的字符串的情况。

希望对您有所帮助

Alan Burstein 正是为此写了一个 iTVF。该函数称为 PatExclude8K。这是函数定义 (删除了一些注释):

CREATE FUNCTION dbo.PatExclude8K
(
    @String VARCHAR(8000),
    @Pattern VARCHAR(50)
) 
/*******************************************************************************
 Purpose:
 Given a string (@String) and a pattern (@Pattern) of characters to remove, 
 remove the patterned characters from the string.
*******************************************************************************/
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
E1(N) AS (SELECT N FROM (VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) AS X(N)),
itally(N) AS 
(
  SELECT TOP(CONVERT(INT,LEN(@String),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
  FROM E1 T1 CROSS JOIN E1 T2 CROSS JOIN E1 T3 CROSS JOIN E1 T4
) 
SELECT NewString =
((
  SELECT SUBSTRING(@String,N,1)
  FROM iTally
  WHERE 0 = PATINDEX(@Pattern,SUBSTRING(@String COLLATE Latin1_General_BIN,N,1))
  FOR XML PATH(''),TYPE
).value('.[1]','varchar(8000)'));
GO

下面是您将如何使用它:

SELECT *
FROM #Programme p
CROSS APPLY dbo.PatExclude8K(p.ProgrammeID, '[0-9]');

使用您的示例数据,结果如下:

ProgrammeID          NewString
-------------------- -----------------
Prog201604L          ProgL
Prog201503L          ProgL
Pro2015N             ProN
Pro2014N             ProN
Programme2010        Programme
Programme2011        Programme

我创建这个解决方案的基础是从字符串中的逗号分隔列表中提取值的解决方案。 它似乎工作 find 甚至比使用 while 更有效 - 不过,我很乐意收到有关该假设的反馈。

在 table 上使用 461.358 行执行此操作需要 3 分 27 秒(每行 0.44 毫秒)(我将其放入函数中)。

select count(*)
from Mytable
where dbo.StripNumeric(inputFromUser) is null

这是解决方案 剥离数字:

declare @input nvarchar(max) = null
select @input = '1a2    3b4' + char(13) + char(10) + '5(678)*90c'
DECLARE @output nvarchar(max) = '';
    WITH cte AS
        (
          SELECT cast(1 as  int) as [index]
            UNION ALL
            SELECT [index]+ 1 as [index]
          from cte
          where [index] < len(@input)  
        )
        select @output =  iif(PATINDEX('%[0-9]%', substring(@input, [index], 1))= 1, @output, @output + substring(@input, [index], 1))
         from cte;
    select iif(COALESCE( @output, '') = '', null, ltrim(rtrim(@output)))

用于剥离非数字:

declare @input nvarchar(max) = null
select @input = '1a2    3b4' + char(13) + char(10) + '5(678)*90c'
DECLARE @output nvarchar(max) = '';
    WITH cte AS
        (
          SELECT cast(1 as  int) as [index]
            UNION ALL
            SELECT [index]+ 1 as [index]
          from cte
          where [index] < len(@input)  --len(substring(@input, index, 1)) >
        )
        select @output =  iif(PATINDEX('%[0-9]%', substring(@input, [index], 1))= 1, @output + substring(@input, [index], 1), @output)
        from cte;
    select iif(COALESCE( @output, '') = '', null, ltrim(rtrim(@output)))