T-SQL选择查询以删除非数字字符

SQL*_*oob 54 t-sql substring sql-server-2008-r2 patindex

我在具有可变alpha长度的列中有脏数据.我只想删除任何不是0-9的东西.

我不想运行函数或proc.我有一个类似于在文本之后抓取数值的脚本,它看起来像这样:

Update TableName
set ColumntoUpdate=cast(replace(Columnofdirtydata,'Alpha #','') as int)
where Columnofdirtydata like 'Alpha #%'
And ColumntoUpdate is Null
Run Code Online (Sandbox Code Playgroud)

我认为它会工作得很好,直到我发现我认为只有Alpha#12345789格式的某些数据字段不...

需要剥离的数据示例

AB ABCDE # 123
ABCDE# 123
AB: ABC# 123
Run Code Online (Sandbox Code Playgroud)

我只想要123.确实所有数据字段都具有#之前的数字.

我尝试了substring和PatIndex,但我的语法不正确或者其他东西.任何人对解决这个问题的最佳方法有任何建议吗?

谢谢!

Ken*_*rds 72

请参阅此博客文章,了解从SQL Server中的字符串中提取数字.下面是您的示例中使用字符串的示例:

DECLARE @textval NVARCHAR(30)
SET @textval = 'AB ABCDE # 123'

SELECT LEFT(SUBSTRING(@textval, PATINDEX('%[0-9.-]%', @textval), 8000),
           PATINDEX('%[^0-9.-]%', SUBSTRING(@textval, PATINDEX('%[0-9.-]%', @textval), 8000) + 'X') -1)
Run Code Online (Sandbox Code Playgroud)

  • 如果您有字符和数字的混合值,则此解决方案不起作用。在 Oracle 中,我只是使用 TRANSLATE 函数来给我数字或 Alpha,但是 SQL Server TRANSLATE 直到 2017 年才可用,而我的公司尚未升级所有实例以供使用。 (5认同)
  • 两条评论:1)我投票认为它是一个直接的表达式,而不是一个过程或函数;2)问题要求删除除0-9之外的*所有*字符。这里的答案需要修改 3 个地方来满足这个要求:将 `0-9.-` 替换为 `0-9`(即删除 3 个地方的 `.-`)。 (4认同)
  • 使用 8000 是因为他要取前 8000 个字符,即 VARCHAR 字符串的最大大小。但是,由于文本被定义为 NVARCHAR,它可能是 4000。我的问题是,这真的有必要吗? (2认同)
  • 这是行不通的。请参阅此示例。设置@textval = 'AB ABC+DE # 123+' (2认同)

Mik*_*son 40

你可以使用东西patindex.

stuff(Col, 1, patindex('%[0-9]%', Col)-1, '')
Run Code Online (Sandbox Code Playgroud)

SQL小提琴

  • 这只会删除第一次出现的非数字字符。 (9认同)
  • 它不会为我删除任何内容。 (2认同)

i-o*_*one 21

如果数字之间可能存在某些字符(例如千位分隔符),您可以尝试以下操作:

declare @table table (DirtyCol varchar(100))
insert into @table values
    ('AB ABCDE # 123')
    ,('ABCDE# 123')
    ,('AB: ABC# 123')
    ,('AB#')
    ,('AB # 1 000 000')
    ,('AB # 1`234`567')
    ,('AB # (9)(876)(543)')

;with tally as (select top (100) N=row_number() over (order by @@spid) from sys.all_columns),
data as (
    select DirtyCol, Col
    from @table
        cross apply (
            select (select C + ''
            from (select N, substring(DirtyCol, N, 1) C from tally where N<=datalength(DirtyCol)) [1]
            where C between '0' and '9'
            order by N
            for xml path(''))
        ) p (Col)
    where p.Col is not NULL
)
select DirtyCol, cast(Col as int) IntCol
from data
Run Code Online (Sandbox Code Playgroud)

输出是:

DirtyCol              IntCol
--------------------- -------
AB ABCDE # 123        123
ABCDE# 123            123
AB: ABC# 123          123
AB # 1 000 000        1000000
AB # 1`234`567        1234567
AB # (9)(876)(543)    9876543
Run Code Online (Sandbox Code Playgroud)

要进行更新,请添加ColToUpdate以选择datacte 列表:

;with num as (...),
data as (
    select ColToUpdate, /*DirtyCol, */Col
    from ...
)
update data
set ColToUpdate = cast(Col as int)
Run Code Online (Sandbox Code Playgroud)


BBa*_*r42 17

这适合我:

CREATE FUNCTION [dbo].[StripNonNumerics]
(
  @Temp varchar(255)
)
RETURNS varchar(255)
AS
Begin

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

    Return @Temp
End
Run Code Online (Sandbox Code Playgroud)

然后像这样调用函数来查看清理过的东西旁边的原始内容:

SELECT Something, dbo.StripNonNumerics(Something) FROM TableA
Run Code Online (Sandbox Code Playgroud)


Har*_*rry 11

聚会已经很晚了,我发现了以下内容,我认为它工作得非常出色……如果有人还在寻找

SELECT
    (SELECT CAST(CAST((
        SELECT SUBSTRING(FieldToStrip, Number, 1)
        FROM master..spt_values
        WHERE Type='p' AND Number <= LEN(FieldToStrip) AND
            SUBSTRING(FieldToStrip, Number, 1) LIKE '[0-9]' FOR XML Path(''))
    AS xml) AS varchar(MAX)))
FROM
    SourceTable
Run Code Online (Sandbox Code Playgroud)


Cle*_*ent 10

如果您的服务器支持TRANSLATE功能,那么这是一个优雅的解决方案(在sql server上,它可以在sql server 2017+和sql azure上使用).

首先,它用@字符替换任何非数字字符.然后,它删除所有@字符.您可能需要添加您知道可能存在于TRANSLATE调用的第二个参数中的其他字符.

select REPLACE(TRANSLATE([Col], 'abcdefghijklmnopqrstuvwxyz+()- ,#+', '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'), '@', '')
Run Code Online (Sandbox Code Playgroud)

  • 我不知道它是否优雅(但相当实用),但它很有效,所以我认为 (2认同)

Elm*_*r C 7

CREATE FUNCTION FN_RemoveNonNumeric (@Input NVARCHAR(512))
RETURNS NVARCHAR(512)
AS
BEGIN
DECLARE @Trimmed NVARCHAR(512)

SELECT @Trimmed = @Input

WHILE PATINDEX('%[^0-9]%', @Trimmed) > 0
    SELECT @Trimmed = REPLACE(@Trimmed, SUBSTRING(@Trimmed, PATINDEX('%[^0-9]%', @Trimmed), 1), '')

RETURN @Trimmed
END

GO

SELECT dbo.FN_RemoveNonNumeric('ABCDE# 123')
Run Code Online (Sandbox Code Playgroud)


Jes*_*ler 5

用这个:

REPLACE(TRANSLATE(SomeString, REPLACE(TRANSLATE(SomeString, '0123456789', '##########'), '#', ''), REPLICATE('#', LEN(REPLACE(TRANSLATE(SomeString, '0123456789', '##########'), '#', '') + 'x') - 1)), '#', '')
Run Code Online (Sandbox Code Playgroud)

演示:

DROP TABLE IF EXISTS #MyTempTable;

CREATE TABLE #MyTempTable (SomeString VARCHAR(255));

INSERT INTO #MyTempTable
VALUES ('ssss123ssg99d362sdg')
    , ('hey 62q&*^(n43')
    , (NULL)
    , ('')
    , ('hi')
    , ('123');

SELECT SomeString
    , REPLACE(TRANSLATE(SomeString, REPLACE(TRANSLATE(SomeString, '0123456789', '##########'), '#', ''), REPLICATE('#', LEN(REPLACE(TRANSLATE(SomeString, '0123456789', '##########'), '#', '') + 'x') - 1)), '#', '')
FROM #MyTempTable;

DROP TABLE IF EXISTS #MyTempTable;
Run Code Online (Sandbox Code Playgroud)

结果:

一些字符串 (无列名)
ssss123ssg99d362sdg 12399362
嘿62q&*^(n43 6243
无效的 无效的
你好
123 123