【问题标题】:Formatting Numbers by padding with leading zeros in SQL Server通过在 SQL Server 中使用前导零填充来格式化数字
【发布时间】:2012-03-20 05:02:59
【问题描述】:

我们有一个旧的 SQL 表,它被 SQL Server 2000 使用了将近 10 年。

在其中,我们的员工徽章编号存储为char(6),从000001999999

我现在正在编写一个 Web 应用程序,我需要存储员工徽章编号。

在我的新表中,我可以走捷径并复制旧表,但我希望通过简单地将 int 值从 1 存储到 999999 来实现更好的数据传输、更小的大小等.

在 C# 中,我可以使用以下方法快速格式化 int 的徽章编号值

public static string GetBadgeString(int badgeNum) {
  return string.Format("{0:000000}", badgeNum);
  // alternate
  // return string.Format("{0:d6}", badgeNum);
}

如何修改这个简单的 SQL 查询以格式化返回值?

SELECT EmployeeID
FROM dbo.RequestItems
WHERE ID=0

如果 EmployeeID 是 7135,则此查询应返回 007135

【问题讨论】:

  • 既然前导 0s 对这个领域很重要,为什么要把它改成 INT 呢?
  • SQL Server 2012最终将拥有类似 C# 的 FORMAT 函数 :-)
  • @Oden:int 值占用的空间比char(6) 少得多,而且每个制造的零件都会有多个这样的条目。效率。
  • 您是否在遇到问题之前进行了优化?
  • 让我们看看,您有多达 100 万个徽章编号,并且您认为每个可以保存(根据 DATALENGTH())两个字节。由于该列可能在索引中,因此您可以节省超过 2MB。再加上其他列,这 2 个字节可能足以减少行的长度,足以每行节省 4KB 的页面。这将托管在移动平台上,还是您可能将注意力集中在非生产性领域?

标签: sql sql-server tsql string-formatting


【解决方案1】:

将数字 6 更改为您需要的总长度:

SELECT REPLICATE('0',6-LEN(EmployeeId)) + EmployeeId

如果该列是 INT,则可以使用 RTRIM 将其隐式转换为 VARCHAR

SELECT REPLICATE('0',6-LEN(RTRIM(EmployeeId))) + RTRIM(EmployeeId)

以及删除这些 0 并取回“真实”数字的代码:

SELECT RIGHT(EmployeeId,(LEN(EmployeeId) - PATINDEX('%[^0]%',EmployeeId)) + 1)

【讨论】:

  • +1 你甚至向我展示了如何删除 0!让我测试一下,我会把它标记为答案。
  • 您不需要代码来删除零,只需分配或转换为 int,它们将被自动删除。
  • 这只有在传入的值是一个字符串时才有效,如果你传入一个整数,你会得到与传入的相同的值。
  • 虽然它的旧......使用“+ convert (varchar, EmployeeID)”而不是“+ EmployeeID”应该可以解决 int 问题
  • 这是一个好方法,除非 EmployeeId 大于 6 位导致 NULL 结果。联系函数就是答案:SELECT CONCAT(REPLICATE('0',6-LEN(CONVERT(varchar,EmployeeId))) , EmployeeId)
【解决方案2】:

您可以通过这种方式更改您的程序

SELECT Right('000000' + CONVERT(NVARCHAR, EmployeeID), 6) AS EmpIDText, 
       EmployeeID
FROM dbo.RequestItems 
WHERE ID=0 

但是,这假设您的 EmployeeID 是一个数值,并且此代码将结果更改为一个字符串,我建议再次添加原始数值

编辑 当然我没有仔细阅读上面的问题。它表示该字段是char(6),因此 EmployeeID 不是数值。虽然这个答案本身仍然有价值,但它不是上述问题的正确答案。

【讨论】:

  • 这是我认为最干净的方法。谢谢
  • '000000' 真的有必要吗..? '0' 也可以正常工作。只使用一个 0 .. 是否安全?
  • OP 要求一个 6 字符长度的字符串作为结果。具体来说如果 EmployeeID 为 7135,则此查询应返回 007135。仅使用一个“0”返回07135 而不是007135。整个想法是连接到由所有0 转换的EmployeedID 字符串组成的6 个字符字符串,然后从右边缘开始获取6 个字符。无论 ID 是什么长度,上述方法总是返回一个字符串,其中只有达到 6 个字符长度所需的零字符数
  • 它可能是 5 个零 '00000',因为 EmployeeID 将包含至少一位数字。但是REPLICATE() 函数似乎更合适,就像在其他答案中一样
【解决方案3】:
SELECT replicate('0', 6 - len(employeeID)) + convert(varchar, employeeID) as employeeID
FROM dbo.RequestItems 
WHERE ID=0

【讨论】:

    【解决方案4】:
    SELECT 
        cast(replace(str(EmployeeID,6),' ','0')as char(6)) 
    FROM dbo.RequestItems
    WHERE ID=0
    

    【讨论】:

    • 哎呀。实际上,当我给它7135时,这给了我7135.0
    【解决方案5】:

    另一种方式,只是为了完整性。

    DECLARE @empNumber INT = 7123
    SELECT STUFF('000000', 6-LEN(@empNumber)+1, LEN(@empNumber), @empNumber)
    

    或者,根据您的查询

    SELECT STUFF('000000', 6-LEN(EmployeeID)+1, LEN(EmployeeID), EmployeeID) 
             AS EmployeeCode
    FROM dbo.RequestItems
    WHERE ID=0
    

    【讨论】:

    • @jp2code - 你需要read up on what StackOverflow is - 它像维基一样协作编辑 - 一旦你发布它就不是你的问题!通常被删掉的东西是过度的“绒毛”,比如提前感谢和糟糕的语法/大写。
    【解决方案6】:

    尽可能干净并给出用变量替换的范围:

    Select RIGHT(REPLICATE('0',6) + EmployeeID, 6) from dbo.RequestItems
    WHERE ID=0
    

    【讨论】:

    • 如果EmployeeID 列定义为int,则+ 运算符将被视为加法而不是串联,因此零会丢失。使用convert 可以避免这个问题。
    • 调用 REPLICATE('0',6) 来避免输入 '000000' 只是浪费 ;-)
    【解决方案7】:

    讨厌必须转换 int,这似乎更简单。由于只有一次字符串转换和简单的加法,因此性能甚至可能更好。

    选择 RIGHT(1000000 + EmployeeId, 6) ...

    只需确保“1000000”的零数至少与所需大小一样多。

    【讨论】:

      【解决方案8】:

      只需使用 FORMAT 函数(适用于 SQL Server 2012 或更高版本):

      SELECT FORMAT(EmployeeID, '000000')
      FROM dbo.RequestItems
      WHERE ID=0 
      

      参考:http://msdn.microsoft.com/en-us/library/hh213505.aspx

      【讨论】:

      • 这是一个老问题——在 SQL Server 2012 出现之前。
      • 不过,我现在希望看到这个气泡离顶部更近一点。
      • 以防万一有人想知道。 Format 不保留数据类型而是隐式转换为 nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
      • 这种方式是最简单的,恕我直言最好的解决方案。
      • SQL Server 中的 FORMAT 仍然通过调用 .NET 的 IFormattable API 来实现,这在从 T-SQL 调用时会增加显着的性能损失。考虑改用stackoverflow.com/a/9520709/159145 中的REPLICATE 方法。这是 2015 年关于 FORMAT 性能不佳的文章:sqlperformance.com/2015/06/t-sql-queries/…
      【解决方案9】:

      从 2012 版起您可以使用

      SELECT FORMAT(EmployeeID,'000000')
      FROM dbo.RequestItems
      WHERE ID=0
      

      【讨论】:

        【解决方案10】:

        我将所有内容都发布在一个地方,所有内容都可以让我用 4 个前导零填充 :)

        declare @number int =  1;
        print right('0000' + cast(@number as varchar(4)) , 4)
        print right('0000' + convert(varchar(4), @number) , 4)
        print right(replicate('0',4) + convert(varchar(4), @number) , 4)
        print  cast(replace(str(@number,4),' ','0')as char(4))
        print format(@number,'0000')
        

        【讨论】:

        • 这涵盖了所有需要的选项。谢谢。
        【解决方案11】:

        该解决方案适用于带前导零的有符号/负数,适用于所有 Sql 版本:

        DECLARE
            @n money = -3,
            @length tinyint = 15,
            @decimals tinyint = 0
        
        SELECT REPLICATE('-', CHARINDEX('-', @n, 1)) + REPLACE(REPLACE(str(@n, @length, @decimals), '-', ''), ' ', '0')
        

        【讨论】:

          【解决方案12】:

          在我的 SQL 版本中,我不能使用 REPLICATE。所以我这样做了:

          SELECT 
              CONCAT(REPEAT('0', 6-LENGTH(emplyeeID)), emplyeeID) AS emplyeeID 
          FROM 
              dbo.RequestItems`
          

          【讨论】:

            【解决方案13】:

            最简单的总是最好的:

            Select EmployeeID*1 as EmployeeID 
            

            【讨论】:

              【解决方案14】:

              考虑负数而不溢出 6 个字符...

              FORMAT(EmployeeID, '000000;-00000')
              

              【讨论】:

                猜你喜欢
                • 2021-02-19
                • 2014-10-29
                • 1970-01-01
                • 2015-05-19
                • 1970-01-01
                • 2020-12-16
                • 1970-01-01
                • 2017-08-26
                • 2012-04-21
                相关资源
                最近更新 更多