繁体   English   中英

如何只将字符串中的数字作为SQL Server中的计算列而不带前导零?

[英]How can I get only numbers from a string as a computed column in SQL Server with no leading zeroes?

背景

目前我有一个函数只从字符串中获取数字(没有前导零)(让我们调用两个变量@alphaNumeric@strippedNumber )。

事实证明,在我查询的表上预先计算@strippedNumber比使用我的函数动态计算它更有效(让我们称之为dbo.fnFormatNumeric )。

设置我的计算列我尝试如下:

ALTER TABLE dbo.Data
ADD StrippedNumber AS CONVERT(BIGINT, dbo.fnFormatNumeric(AlphaNumeric))

这在转换大量数据(大约25,000,000+行)方面非常有效。

尝试升级我的数据库时出现问题 (我们删除并重新创建所有功能)。 所以我试图将该函数排除在外或被重新创建。

错误。 现在我无法安装新数据库,因为它依赖于尚未创建的功能。

理想的场景

我希望能够在不使用函数的情况下从字符串中选择字符串中的所有数字作为计算列。

研究

Sql Authority博客建议使用一个函数来获取数值, 这个答案在SO引用上。 这不是一件好事,因为一个功能会给我带来麻烦。

关于SO的另一个答案建议使用LEFTPATINDEX但这只会得到第一组数字而不是字符串中的所有数字。

关于SO的这个问题并不好,因为它使用ISNUMERIC只获取所有数字都是数字的字符串。

我找到了一篇博文 ,他们使用PATINDEX从字符串中获取数字,但这是假设所有数字都在一起。

投入和预期产出:

@alphaNumeric  =>  @strippedNumber
-----------------------------------
FXADJ011016CR  =>   11016
15-June-2016   =>   152016
708014         =>   708014
FXRWECTB       =>   (empty string)

现有功能:

Input @alphaNumeric varchar(255)    

    DECLARE     @strtoCheckLength       Int,
                @strCount               Int,
                @code                   Int,
                @StrippedNumber varchar(255)
    -- Get and set length and loop variables
    Set @strtoCheckLength = Len(@alphaNumeric)
    Set @strCount = (0)
    Set @StrippedNumber = ''
    -- Make sure we only include Numerics
    While @strCount <= @strtoCheckLength
        Begin
            set @code = Ascii(SubString(@alphaNumeric, @strCount, 1))
            If (@code between 48 and 57) 
                Begin
                    set @StrippedNumber = @StrippedNumber + Substring(@alphaNumeric, @strCount, 1)
                End
            Set @strCount = (@strCount + 1)
        End
    -- Remove Leading Zeros
    While (Len(@StrippedNumber) > 0) And (Left(@StrippedNumber, 1) = '0')
        Begin
            Set @StrippedNumber = Right(@StrippedNumber, Len(@StrippedNumber) - 1)
        End
    Return @StrippedNumber

希望这段代码可以帮助您定义计算列。

本质上,数字表用于通过索引来分解字符串,然后查询将连接的输出强制转换为bigint以在重新转换为varchar之前删除前导零(255)

在生产数据库中,我建议预先定义和填充数字表。 关于如何在www.SqlServerCentral.com上使用它们有很多讨论

--set up a numbers table
select top 50 n=identity(int,1,1) into #temp_numbers from syscolumns

/*
FXADJ011016CR => 11016

15June2016 => 152016

708014 => 708014

FXRWECTB => Empty String
*/

declare @input varchar(50) = 'FXADJ011016CR'
declare @output varchar(50)

select isnull(cast(cast((
    select numericValue as [text()] from (
        select substring(@input, t.n, 1) as numericValue 
            from #temp_numbers t 
            where isnumeric(substring(@input, t.n, 1))=1
        ) tblResults for xml path('')
    ) as bigint) as varchar(255)),'')

drop table #temp_numbers

你可以用它

DECLARE @SampleData AS TABLE
(
   Value varchar(100)
)
INSERT INTO @SampleData
VALUES  ('FXADJ011016CR'),('15June2016'), 
      ('708014 '), ('FXRWECTB ')

DECLARE @RegexNonNumber VARCHAR(30) = '%[^0-9]%'

;WHILE (EXISTS (SELECT 1 FROM @SampleData sd WHERE PatIndex(@RegexNonNumber, sd.[Value]) > 0))
BEGIN
    UPDATE @SampleData
    SET
       [Value] = Stuff([Value], PatIndex(@RegexNonNumber, [Value]), 1, '')
    WHERE PatIndex(@RegexNonNumber, [Value]) > 0

END

SELECT * FROM @SampleData sd

演示链接: Rextester

使用Replace功能将字符Replace为空值。

如下: -

select cast(replace(replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(replace(replace
(@str,'A',''),'B',''),'C',''),'D',''),'E',''),'F',''),'G',''),'H',''),'I',''),'J','')
,'K',''),'L',''),'M',''),'N',''),'O',''),'P',''),'Q',''),'R',''),'S',''),'T','')
,'U',''),'V',''),'W',''),'X',''),'Y',''),'Z',''),'$',''),',',''),' ','') as bigint)

注意:-

这个解决方案很丑陋而且性能很糟糕,但是我把它作为最后的解决方案发布了,希望能比其他解决方案更好。

如果你有25,000,000条记录,那么我建议最好对表格进行反Denormalize

添加标准bigint列。

ALTER TABLE dbo.Data
ADD StrippedNumber AS BIGINT NULL

并使用数据UPDATE列。

UPDATE dbo.Data SET StrippedNumber = CONVERT(BIGINT, dbo.fnFormatNumeric(AlphaNumeric))

此解决方案的唯一缺点是所有插入和更新必须使用AlphaNumeric列中的数据手动更新StrippedNumber列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM