【问题标题】:Getting numbers from character column in T-SQL从 T-SQL 中的字符列获取数字
【发布时间】:2016-06-26 17:50:37
【问题描述】:

我使用 SQL Server。在我的数据库中,我有一列UniqueId,即nvarchar,其中包含带有字符和数字的字符串。我想创建另一列 (CleanColumn),仅从列 UniqueId 中获取数字,如果没有数字则使用整个字符串。我也应该从列UniqueId 中丢失前导零。

在 T-SQL 中可以吗?或者我必须为此使用 C#?

UniqueId 列包含例如::

A01943486
102-2009-1008
A-146
0622008081A
Ematol OPBG
Yavuz1098083
Yeter1391671
YKM
Zabit1446123
Zekerya13128
Zeynep1045201 

【问题讨论】:

  • 你能解释一下这个改变的目的吗?如果您想保留全字母记录,那么您的新列应该仍然是一个 nvarchar 列,具有与当前列相同的问题 (?)
  • 感谢您的关注。这只是一个客户请求,它不是那么合乎逻辑。他们想按 CleanColumn(作为数字)对报告进行排序,但许多字符串在 UniqueId 列中没有数字,因此他们也必须包含字符串。
  • 因此可以放弃排序的整个目的。可能更好的方法是在每个数字和字符串前面用零填充列,然后进行排序。你可以从这个问题中得到一些想法:Formatting Numbers by padding with leading zeros in SQL Server

标签: c# sql-server


【解决方案1】:

这里是 q quick UDF,它只返回数字或原始字符串

ALTER FUNCTION [dbo].[udfNumbersOnly](@String varchar(250))
Returns Varchar(250)
As
Begin
    Declare @RetVal varchar(250) = @String
    ;with cteChar as (Select Cnt=1,Str=Char(1) Union All Select Cnt=B.Cnt+1,Str=Char(B.Cnt+1) From cteChar as B Where B.Cnt <= 255)
    Select @RetVal = Replace(@RetVal,Str,'') From cteChar where str not like '[0-9]' Option (maxrecursion 256)
    Return case when IsNull(@RetVal,'')='' then @String else cast(cast(@RetVal as decimal(20,0)) as varchar(250)) end
END

Select [dbo].[udfNumbersOnly]('0622008081A')   -- Returns 0622008081
Select [dbo].[udfNumbersOnly]('YKM')           -- Returns YKM

所以你的情况

Update YourTableName Set CleanColumn = [dbo].[udfNumbersOnly](UniqueId)

【讨论】:

  • 非常感谢,效果很好。您能否稍微更改一下代码以避免出现前导零? 622008081 而不是 0622008081?
  • 更新删除前导零
  • 再次感谢您:) 很抱歉,当我尝试Select [dbo].[udfNumbersOnly]('Ematol OPBG') 时,我发现一条消息“将 varchar 值 'Ematol OPBG' 转换为数据类型 int 时转换失败”。对于Select [dbo].[udfNumbersOnly]('102-2009-1008'),我有一条消息'varchar 值'10220091008'的转换溢出了一个int 列。'
  • 我更新了答案,增加了一个对 varchar 的强制转换,这应该可以解决问题
  • 保持 1 秒。我从来没有想过这么长的数字字符串。一分钟更新
【解决方案2】:

您可以使用正则表达式 /[0-9]+/ (OR) \d+。下面给出的示例代码(使用C#

    static void Main(string[] args)
    {
        List<string> str = new List<string>() { "A01943486", "102-2009-1008", "A-146", "0622008081A", 
                                                "Ematol OPBG", "Yavuz1098083", "Yeter1391671"};
        List<int> extractedNumbers = new List<int>();

        Regex reg = new Regex("[0-9]+");

        foreach (var item in str)
        {
            Match m = reg.Match(item);
            if (m.Success)
            {
                int num = Convert.ToInt32(m.Value.TrimStart('0'));
                extractedNumbers.Add(num);
            }
        }
    }

【讨论】:

  • 非常感谢。因此,我使用实体框架在 ASP.NET MVC C# 项目中工作。你知道如何在Entity Framework中同时更新“CleanColumn”和UniqueId(而不是T-SQL)吗?
  • @alenan2013,无论是 EF/MVC,它都是 C# 代码,因此您可以将发布的答案代码包装在一个方法中并调用该方法。关于如何使用 EF 更新数据库表中的 cleancolumn 列...这是一个单独的问题,因此建议您为此发布另一个问题/线程。
【解决方案3】:

声明这种设计看起来很奇怪且有问题,是的 - 有可能:

您可以find the first number in the string 然后check if cast is possible 然后使用case statement 来实际投射它。

【讨论】:

  • 感谢您的关注。我会试试的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-13
  • 2015-06-21
  • 1970-01-01
  • 1970-01-01
  • 2022-08-22
  • 2021-12-09
  • 1970-01-01
相关资源
最近更新 更多