Tsql 选择“查询”以删除非数字字符

Tsql 选择“查询”以删除非数字字符,tsql,sql-server-2008-r2,substring,patindex,Tsql,Sql Server 2008 R2,Substring,Patindex,我在一列中有脏数据,alpha长度可变。我只想去掉任何不是0-9的东西 我不想运行函数或进程。我有一个类似的脚本,它只抓取文本后的数字值,如下所示: Update TableName set ColumntoUpdate=cast(replace(Columnofdirtydata,'Alpha #','') as int) where Columnofdirtydata like 'Alpha #%' And ColumntoUpdate is Null 我认为它会很好地工作,直到我发现一些

我在一列中有脏数据,alpha长度可变。我只想去掉任何不是0-9的东西

我不想运行函数或进程。我有一个类似的脚本,它只抓取文本后的数字值,如下所示:

Update TableName
set ColumntoUpdate=cast(replace(Columnofdirtydata,'Alpha #','') as int)
where Columnofdirtydata like 'Alpha #%'
And ColumntoUpdate is Null
我认为它会很好地工作,直到我发现一些我认为只是alpha12345789格式的数据字段不是

需要剥离的数据示例

AB ABCDE # 123
ABCDE# 123
AB: ABC# 123
我只想要123。的确,所有数据字段都在数字之前有

我尝试了substring和PatIndex,但语法不太正确。有人对解决这个问题的最佳方法有什么建议吗?

请参阅有关在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)
您可以使用和

填充列,1,patindex“[0-9]”,列1,
如果数字之间可能存在某些字符,例如千位分隔符,您可以尝试以下操作:

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
对于更新,添加ColToUpdate以选择数据cte的列表:


这对我来说很有效:

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
然后像这样调用函数以查看经过消毒的对象旁边的原始对象:

SELECT Something, dbo.StripNonNumerics(Something) FROM TableA
为了补充答案,它处理逗号、空格和括号

--Handles parentheses, commas, spaces, hyphens..
declare @table table (c varchar(256))
insert into @table
values
('This is a test 111-222-3344'),
('Some Sample Text (111)-222-3344'),
('Hello there 111222 3344 / How are you?'),
('Hello there 111 222 3344 ? How are you?'),
('Hello there 111 222 3344. How are you?')

select
replace(LEFT(SUBSTRING(replace(replace(replace(replace(replace(c,'(',''),')',''),'-',''),' ',''),',',''), PATINDEX('%[0-9.-]%', replace(replace(replace(replace(replace(c,'(',''),')',''),'-',''),' ',''),',','')), 8000),
           PATINDEX('%[^0-9.-]%', SUBSTRING(replace(replace(replace(replace(replace(c,'(',''),')',''),'-',''),' ',''),',',''), PATINDEX('%[0-9.-]%', replace(replace(replace(replace(replace(c,'(',''),')',''),'-',''),' ',''),',','')), 8000) + 'X') -1),'.','')
from @table

这是一个从字符串中提取所有数字的版本;i、 e.考虑到我35岁;我出生于1982年。平均每个家庭有2.4个孩子。这将返回35198224。i、 e.如果您有可能已被格式化为代码的数字数据,例如123456789/123-00005,这是很好的,但如果您希望从文本中提取特定的数字,即与数字/仅数字字符相反,这是不合适的。而且它只处理数字;所以不会返回负号或句号

这段代码的工作原理是用空格替换给定字符串中的所有数字,即我们想要的字符。然后遍历原始字符串,其中包括删除所有剩余字符(即非数字字符)的数字,从而只留下数字

我们分两步完成这项工作,而不是首先删除所有非数字字符的原因是只有10位数字,而可能的字符数量巨大;因此,取代小名单相对较快;然后给我们一个字符串中实际存在的非数字字符的列表,这样我们就可以替换这个小集合


该方法使用递归SQL,使用常见的表表达式CTE。

如果您的服务器支持SQL server上的翻译功能,那么这是一个优雅的解决方案,它在SQL server 2017+和SQL azure上都可用

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

select REPLACE(TRANSLATE([Col], 'abcdefghijklmnopqrstuvwxyz+()- ,#+', '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'), '@', '')

我已经为此创建了一个函数

Create FUNCTION RemoveCharacters (@text varchar(30))
RETURNS VARCHAR(30)
AS
BEGIN
declare @index as int 
declare @newtexval as varchar(30)
set @index = (select PATINDEX('%[A-Z.-/?]%', @text))
if (@index =0)
begin 
return @text
end
else
begin 
set @newtexval  = (select STUFF ( @text , @index , 1 , '' ))
return dbo.RemoveCharacters(@newtexval)
end
return 0
END
GO
答案如下:

DECLARE @t TABLE (tVal VARCHAR(100))

INSERT INTO @t VALUES('123')
INSERT INTO @t VALUES('123S')
INSERT INTO @t VALUES('A123,123')
INSERT INTO @t VALUES('a123..A123')


;WITH cte (original, tVal, n)
     AS
     (
         SELECT t.tVal AS original,
                LOWER(t.tVal)  AS tVal,
                65             AS n
         FROM   @t             AS t
         UNION ALL
         SELECT tVal AS original,
                CAST(REPLACE(LOWER(tVal), LOWER(CHAR(n)), '') AS VARCHAR(100)),
                n + 1
         FROM   cte
         WHERE  n <= 90
     )

SELECT t1.tVal  AS OldVal,
       t.tval   AS NewVal
FROM   (
           SELECT original,
                  tVal,
                  ROW_NUMBER() OVER(PARTITION BY tVal + original ORDER BY original) AS Sl
           FROM   cte
           WHERE  PATINDEX('%[a-z]%', tVal) = 0
       ) t
       INNER JOIN @t t1
            ON  t.original = t1.tVal
WHERE  t.sl = 1
这对我很有用:

我删除了单引号

然后我用一个替换,用

这肯定会对某人有所帮助:

" & txtFinalscore.Text.Replace(",", ".") & "

在您的例子中,似乎符号总是在符号之后,因此将CHARINDEX与LTRIM和RTRIM一起使用可能会表现得最好。但这里有一个有趣的方法,可以去掉任何非数字。它使用计数表和数字表来限制接受哪些字符,然后使用XML技术连接回一个没有非数字字符的字符串。这项技术的妙处在于,它可以扩展到包含任何允许的字符,并删除任何不允许的字符

DECLARE @ExampleData AS TABLE (Col VARCHAR(100))
INSERT INTO @ExampleData (Col) VALUES ('AB ABCDE # 123'),('ABCDE# 123'),('AB: ABC# 123')

DECLARE @Digits AS TABLE (D CHAR(1))
INSERT INTO @Digits (D) VALUES ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9')

;WITH cteTally AS (
SELECT
    I = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
    @Digits d10
    CROSS APPLY @Digits d100
    --add more cross applies to cover longer fields this handles 100
)

SELECT *
FROM
    @ExampleData e
    OUTER APPLY (
    SELECT CleansedPhone = CAST((
    SELECT TOP 100
       SUBSTRING(e.Col,t.I,1)
    FROM
       cteTally t
       INNER JOIN @Digits d
       ON SUBSTRING(e.Col,t.I,1) = d.D
    WHERE
       I <= LEN(e.Col)
    ORDER BY
       t.I
    FOR XML PATH('')) AS VARCHAR(100))) o

您可以创建SQLCLR标量函数,以便能够使用诸如替换模式之类的正则表达式

您可以找到如何创建此类函数的示例

具有此功能将通过以下几行解决问题:

SELECT [dbo].[fn_Utils_RegexReplace] ('AB ABCDE # 123', '[^0-9]', '');
SELECT [dbo].[fn_Utils_RegexReplace] ('ABCDE# 123', '[^0-9]', '');
SELECT [dbo].[fn_Utils_RegexReplace] ('AB: ABC# 123', '[^0-9]', '');

更重要的是,您将能够解决更复杂的问题,因为正则表达式将直接在您的T-SQL语句中带来全新的选项世界。

DECLARE@STR VARCHAR400

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')
声明@specialchars VARCHAR50='%[~,@,,$,%,&,*,,!^?:]%

SET@STR='1,454,368.00-'

而PATINDEX@specialchars,@STR>0

--使用替换功能删除特殊字符

SET@STR=replace@STR,SUBSTRING@STR,PATINDEX@specialchars,@STR,1,,“-”,“


选择@STR

晚会很晚了,我发现了以下我认为做得很出色的东西。。如果有人还在找的话

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

相关:可能重复的。你能解释一下你的答案吗?为什么答案中使用数字8000?使用8000是因为他使用了前8000个字符,一个VARCHAR字符串的最大大小。然而,由于文本被定义为NVARCHAR,它可能是4000。我的问题是,这真的有必要吗?两条评论:我投赞成票
是一个直接的表达式,而不是一个过程或函数;2要求删除除0-9以外的所有字符的问题。这里的答案需要在3处修改以满足此要求:将0-9.-替换为0-9,即在3处删除。-如果字符和数字的值混合,则此解决方案不起作用。在Oracle中,我只是使用TRANSLATE函数来提供数字或Alpha,但SQL Server TRANSLATE直到2017年才可用,我的公司尚未升级所有实例以供使用。这不起作用。看看这个例子。SET@textval='AB ABC+DE 123+'这只会删除第一次出现的非数字字符。它不会为我删除任何字符。非常感谢!你是个救生员。我修改了您的正则表达式,使其包含小数点集@KeepValues='%[^0-9].%',但除此之外,整个代码都能像预期的那样完美地工作;非常好的解决方案。谢谢!这应该是公认的答案。你可以把它变成一个内联函数,它的执行速度会比这里提到的其他函数快。OP要求删除T-SQL中的非数字字符,这个答案是用逗号替换另一种语言中的点。。。
" & txtFinalscore.Text.Replace(",", ".") & "
DECLARE @ExampleData AS TABLE (Col VARCHAR(100))
INSERT INTO @ExampleData (Col) VALUES ('AB ABCDE # 123'),('ABCDE# 123'),('AB: ABC# 123')

DECLARE @Digits AS TABLE (D CHAR(1))
INSERT INTO @Digits (D) VALUES ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9')

;WITH cteTally AS (
SELECT
    I = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
    @Digits d10
    CROSS APPLY @Digits d100
    --add more cross applies to cover longer fields this handles 100
)

SELECT *
FROM
    @ExampleData e
    OUTER APPLY (
    SELECT CleansedPhone = CAST((
    SELECT TOP 100
       SUBSTRING(e.Col,t.I,1)
    FROM
       cteTally t
       INNER JOIN @Digits d
       ON SUBSTRING(e.Col,t.I,1) = d.D
    WHERE
       I <= LEN(e.Col)
    ORDER BY
       t.I
    FOR XML PATH('')) AS VARCHAR(100))) o
SELECT [dbo].[fn_Utils_RegexReplace] ('AB ABCDE # 123', '[^0-9]', '');
SELECT [dbo].[fn_Utils_RegexReplace] ('ABCDE# 123', '[^0-9]', '');
SELECT [dbo].[fn_Utils_RegexReplace] ('AB: ABC# 123', '[^0-9]', '');
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')
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