在SQL Server中通过填充前导零来格式化数字


119

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

在其中,我们的员工证件编号存储为char(6)000001999999

我现在正在编写一个Web应用程序,并且需要存储员工证卡号。

在我的新表中,我可以使用快捷方式来复制旧表,但是我希望通过简单地存储intfrom 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全部更改为?
Oded

2
SQL Server 2012 最终将具有FORMAT类似C#的功能:-)
marc_s

1
@Oden:int值占用的空间明显少于char(6),并且要制造的每个零件将有多个这些条目。效率。
jp2code 2012年

在遇到问题之前是否正在优化?
奥德

4
让我们看一下,您有多达一百万个徽章编号,并且您认为可以分别保存(根据DATALENGTH())两个字节。由于该列可能在索引中,因此您可以节省超过2MB。加上其他列,这2个字节可能足以减少一行的长度,从而每行节省4KB页面。这是要在移动平台上托管,还是您可能将注意力集中在非生产性领域?
HABO 2012年

Answers:


172

将数字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
+1您甚至还向我展示了如何删除0!让我测试一下,然后将其标记为答案。
jp2code 2012年

您不需要删除零的代码,只需分配或转换为int即可自动删除它们。
Jimbo 2012年

2
这只能如果传入的值是一个字符串,如果你的整数关口,你出去,你在传递相同的值。
Mordy

2
尽管它的旧版本...使用“ + convert(varchar,EmployeeID)”而不是“ + EmployeeID”应该可以解决int问题
Krishna Sarma 2014年

3
除非EmployeeId大于6位数字(导致NULL结果),否则这是一个好方法。联系人函数就是答案:SELECT CONCAT(REPLICATE('0',6-LEN(CONVERT(varchar,EmployeeId))),EmployeeId)
Mahmoud Moravej 2015年

125

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

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

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


1
这是一个老问题-在SQL Server 2012发布之前。
jp2code 2014年

19
不过,我仍然希望看到这个泡沫离顶部更近一些。
Dave Haynes 2014年

4
以防万一有人想知道。Format不保留数据类型,而是隐式转换为nvarchar:select sql_variant_property(50, 'BaseType'), sql_variant_property(format(50, N'00000'), 'BaseType')
Ralph 2015年

2
这种方式是最简单的方法,也是恕我直言的最佳解决方案。
罗伯特·卢霍

如果要对大型数据集使用此功能,请注意此功能
amd 2016年

33

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

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

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

编辑当然,我没有仔细阅读上面的问题。它说该字段是一个char(6)EmployeeID而不是一个数值。尽管此答案本身仍然具有价值,但它并不是上述问题的正确答案。


我认为这是最干净的方法。谢谢
iheartcsharp 2013年

是不是'000000'真的有必要..?'0'也很好。仅使用一个0 ..是否安全?
shashwat 2013年

1
OP要求输入6个字符的字符串作为结果。具体来说,如果EmployeeID为7135,则此查询应返回007135。仅使用一个“ 0” 07135不会返回007135。整个想法是将所有0转换为EmployeedID的字符串组成的6个字符的字符串连接起来,然后从右边开始STARTING取6个字符。无论ID的长度是多少,上面的方法始终返回一个字符串,该字符串仅具有达到6个字符长度所需的零个字符数
Steve

它可能是5个零,'00000'因为EmployeeID将会包含至少一位数字。但是该REPLICATE()功能似乎更合适,就像其他答案一样
nosklo 2014年

26

讨厌不得不转换int,这似乎要简单得多。因为只有一个字符串转换和简单的添加,所以甚至可能会表现更好。

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

只要确保“ 1000000”的零个数至少等于所需的大小即可。


11

我将所有内容发布到一个地方,所有工作对我来说都是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')

这涵盖了所有必需的选项。谢谢。
kyurthich

6

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

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-您需要阅读什么是StackOverflow-像Wiki一样进行协同编辑- 发布后,这不是您的问题!通常被编辑掉的东西是过多的“绒毛”,例如预先感谢和语法/大写不佳。
Jamiec


4

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

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

如果将该EmployeeID列定义为,int则+运算符将被视为加法运算而不是串联运算,因此零将丢失。使用convert将避免此问题。

调用REPLICATE('0',6)避免键入'000000'只是浪费;-)
Mladen Mihajlovic

3
SELECT replicate('0', 6 - len(employeeID)) + convert(varchar, employeeID) as employeeID
FROM dbo.RequestItems 
WHERE ID=0

2
SELECT 
    cast(replace(str(EmployeeID,6),' ','0')as char(6)) 
FROM dbo.RequestItems
WHERE ID=0

哎呀 实际上,这是我给我的7135.0时候给的7135
jp2code 2012年

1

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

DECLARE
    @n money = -3,
    @length tinyint = 15,
    @decimals tinyint = 0

SELECT REPLICATE('-', CHARINDEX('-', @n, 1)) + REPLACE(REPLACE(str(@n, @length, @decimals), '-', ''), ' ', '0')

1

最简单的总是最好的:

Select EmployeeID*1 as EmployeeID 

-1

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

SELECT 
    CONCAT(REPEAT('0', 6-LENGTH(emplyeeID)), emplyeeID) AS emplyeeID 
FROM 
    dbo.RequestItems`
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.