用前导零填充字符串,因此在SQL Server 2008中为3个字符长


398

在SQL Server 2008 R2中首次创建时,我的字符串最长为3个字符。

我想用前导零填充它,因此,如果其原始值是“ 1”,那么新值将是“ 001”。或者,如果其原始值为'23',则新值为'023'。或者,如果其原始值为“ 124”,则新值与原始值相同。

我正在使用SQL Server 2008 R2。我将如何使用T-SQL做到这一点?



Answers:


681

如果该字段已经是字符串,则可以使用

 SELECT RIGHT('000'+ISNULL(field,''),3)

如果您希望null显示为'000'

它可能是整数-那么您需要

 SELECT RIGHT('000'+CAST(field AS VARCHAR(3)),3)

根据问题的要求,此答案仅在长度<= 3时有效,如果要更大,则需要将字符串常量和两个整数常量更改为所需的宽度。例如'0000' and VARCHAR(4)),4


8
我有一个Char(6)字段,其中只有几个2-3个字符长的值,而上面的值对我不起作用。我必须在'000000'+ ISNULL(FIELD,'')周围添加RTRIM才能正常工作。
DWiener 2014年

3
Hogan是的,我明白了,但是无论字符串不能工作多长时间,我都有点忙于找出原因,但是要点在于,我的CHAR(6)字段只执行RIGHT('000000 '+ ISNULL(field,''),6)不起作用,而RIGHT(RTRIM('000000'+ ISNULL(field,'')),6)起作用。
DWiener 2014年

2
哦,我知道,您在编码为字符串的数字的右边有空格。
霍根

3
@dwiener之所以会出现这种现象,是因为char是固定长度的数据类型,因此在您的情况下char(6)表示6个字符长。如果您的实际值小于6,则会在右边用空格填充,因此建议的答案将对char(6)产生错误的结果。
Giannis Paraskevopoulos

2
@Hogan,是的,但是这个问题是“ sql添加前导零”的top1 google结果,所以我认为这对于许多人(不使用sqlserver,但是使用google这个问题)知道其他数据库中的内容可能是有用的存在更方便的功能lpad。还是要谢谢你。
diralik '17

142

尽管问题是针对SQL Server 2008 R2的,但如果有人使用2012年及更高版本阅读此书,此后,使用FORMAT变得容易得多。

您可以传递标准数字格式字符串自定义数字格式字符串作为格式参数(感谢Vadim Ovchinnikov的提示)。

对于这个问题,例如一个类似的代码

DECLARE @myInt INT = 1;
-- One way using a standard numeric format string
PRINT FORMAT(@myInt,'D3');
-- Other way using a custom numeric format string
PRINT FORMAT(@myInt,'00#');

输出

001
001

2
如果输入数字为111或11,会怎样?
霍根

6
1这是001,11是011和111这是111
盖佐

2
您可以使用“ D3”代替“ 00#”。
Vadim Ovchinnikov

1
它似乎比接受的答案要慢得多,但是如果不处理大量数据,那么就容易得多
root

2
尽管看起来不合逻辑,但值得注意的是FORMAT仅适用于数字和日期类型,不适用于varchar。
strattonn

120

安全方法:

SELECT REPLACE(STR(n,3),' ','0')

这具有返回'***'n <0或n> 999 的字符串的优点,这是输入越界的一个很好的明显指示。此处列出的其他方法将通过截断3个字符的子字符串的输入而无提示地失败。


10
该死的,无论谁登陆到此页面,都应该帮助它漂浮到顶部!
MarioDS

1
请谨慎使用此方法。当表达式超过指定的长度时,字符串将为指定的长度返回**。对于例如str(n,10),当n = 1000000000时,您将出现星星(*)。
未绑定,

我不知道这是如何工作的,但是非常简单。
RaRdEvA

1
小心使用此字符串,字符串会破坏它(OP要求“填充字符串”)。作品:SELECT REPLACE(STR('1',3),' ','0')休息时间:SELECT REPLACE(STR('1A',3),' ','0')。今天,当用户在输入字符串中输入字母而我无法测试这种情况时,这真让我很烦。
Jeff Mergler,

@Unbound这就是它的工作方式,发布者已经说过了。像其他所有建议一样,返回***比截断值还好,这表明参数错误。
Marc Guillot

32

这是一种用于将左侧填充到任何所需宽度的更通用的技术:

declare @x     int     = 123 -- value to be padded
declare @width int     = 25  -- desired width
declare @pad   char(1) = '0' -- pad character

select right_justified = replicate(
                           @pad ,
                           @width-len(convert(varchar(100),@x))
                           )
                       + convert(varchar(100),@x)

但是,如果要处理负值,并用前导零填充,则此方法或其他建议的方法都将无效。您将获得如下所示的内容:

00-123

[可能不是您想要的]

所以……您将不得不跳过一些额外的步骤,这是一种可以正确设置负数格式的方法:

declare @x     float   = -1.234
declare @width int     = 20
declare @pad   char(1) = '0'

select right_justified = stuff(
         convert(varchar(99),@x) ,                            -- source string (converted from numeric value)
         case when @x < 0 then 2 else 1 end ,                 -- insert position
         0 ,                                                  -- count of characters to remove from source string
         replicate(@pad,@width-len(convert(varchar(99),@x)) ) -- text to be inserted
         )

应该注意的是,convert()调用应指定[n]varchar足够长的长度,以保留截断后的转换结果。


2
@StenPetrov,谢谢。这完全取决于您要完成的工作。我已经学会在大型的实际生产数据库中依赖的一件事是存在一种或另一种不良数据。而且,我更愿意避免在凌晨3点打电话; ^)
Nicholas Carey 2014年

:)仍然有3AM呼叫时,我还是要读1条简单的行而不是10条复杂的行。添加变量进一步使情况变得更糟,尤其是如果另一个团队成员决定即时计算它们并且不检查非负@width ...
Sten Petrov

这些添加的变量仅用于一般化-您可以对值进行硬编码。对于一个内衬,您可以创建一个标量函数-然后就拥有一个内衬。
Gerard ONeill

30

这是我在SQL Server Express 2012中使用的Hogan答案的一种变体:

SELECT RIGHT(CONCAT('000', field), 3)

我只是担心CONCAT它,而不用担心该字段是否是字符串,因为它仍然会输出字符串。此外,如果该字段可以是NULL,则ISNULL可能需要使用,以避免函数获得NULL结果。

SELECT RIGHT(CONCAT('000', ISNULL(field,'')), 3)

1
据我所知,CONCAT只是忽略该值为null的值,因此第一个可以正常工作。
玛丽

无论Field的长短如何,此解决方案都将起作用
Unbound

23

我一直发现以下方法非常有帮助。

REPLICATE('0', 5 - LEN(Job.Number)) + CAST(Job.Number AS varchar) as 'NumberFull'

15

使用适合各种情况的此功能。

CREATE FUNCTION dbo.fnNumPadLeft (@input INT, @pad tinyint)
RETURNS VARCHAR(250)
AS BEGIN
    DECLARE @NumStr VARCHAR(250)

    SET @NumStr = LTRIM(@input)

    IF(@pad > LEN(@NumStr))
        SET @NumStr = REPLICATE('0', @Pad - LEN(@NumStr)) + @NumStr;

    RETURN @NumStr;
END

样品输出

SELECT [dbo].[fnNumPadLeft] (2016,10) -- returns 0000002016
SELECT [dbo].[fnNumPadLeft] (2016,5) -- returns 02016
SELECT [dbo].[fnNumPadLeft] (2016,2) -- returns 2016
SELECT [dbo].[fnNumPadLeft] (2016,0) -- returns 2016 

这应该是公认的答案,因为它适用于数字和字符串。而且,如果您不想使用某个函数(但为什么不使用),则类似的方法也可以使用:DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 12 - LEN(@NumStr)) + @NumStr;它返回上述Salar的第一个示例。谢谢撒拉尔。
Jeff Mergler,

我在上面的评论中包含一个错字,应显示为:在上面的第一个示例中DECLARE @NumStr VARCHAR(250) = '2016'; SELECT REPLICATE('0', 10 - LEN(@NumStr)) + @NumStr;返回0000002016
Jeff Mergler,

@JeffMergler-如何处理数字和字符串?它是一个带有整数参数的函数。问题是关于字符串的。
霍根

5

对于那些想要更新其现有数据的人,这里是查询:

update SomeEventTable set eventTime=RIGHT('00000'+ISNULL(eventTime, ''),5)

3

对于整数,可以使用从int到varchar的隐式转换:

SELECT RIGHT(1000 + field, 3)

4
但是,如果给出足够大的值,那将失败,此外,对于负值,您将获得...有趣的结果。
Nicholas Carey 2014年

3

我知道它的旧票,我只是想分享一下。

我发现此代码正在寻找解决方案。不知道它是否适用于所有版本的MSSQL我有MSSQL 2016。

declare @value as nvarchar(50) = 23
select REPLACE(STR(CAST(@value AS INT) + 1,4), SPACE(1), '0') as Leadingzero

返回“ 0023” STR函数中的4是包括该值的总长度。示例4、23和123的STR都将为4,并且将添加正确数量的零。您可以增加或减少它。无需获取23上的长度。

编辑:我看到它与@Anon帖子相同。


2

当需要固定大小的varchar(或字符串)输出时,整数列作为输入存在类似问题。例如,1到'01',12到'12'。此代码有效:

SELECT RIGHT(CONCAT('00',field::text),2)

如果输入也是varchar的列,则可以避免转换部分。


2

对于更动态的方法,请尝试此操作。

declare @val varchar(5)
declare @maxSpaces int
set @maxSpaces = 3
set @val = '3'
select concat(REPLICATE('0',@maxSpaces-len(@val)),@val)

2

尝试使用固定长度。

select right('000000'+'123',5)

select REPLICATE('0', 5 - LEN(123)) + '123'

1

之所以这样写是因为我对特定长度的要求最高(9)。仅当需要填充输入时,才用@pattern填充左侧。应始终返回@pattern中定义的长度。

declare @charInput as char(50) = 'input'

--always handle NULL :)
set @charInput = isnull(@charInput,'')

declare @actualLength as int = len(@charInput)

declare @pattern as char(50) = '123456789'
declare @prefLength as int = len(@pattern)

if @prefLength > @actualLength
    select Left(Left(@pattern, @prefLength-@actualLength) + @charInput, @prefLength)
else
    select @charInput

返回1234input


1

简单的是

喜欢:

DECLARE @DUENO BIGINT
SET @DUENO=5

SELECT 'ND'+STUFF('000000',6-LEN(RTRIM(@DueNo))+1,LEN(RTRIM(@DueNo)),RTRIM(@DueNo)) DUENO

0

我专门来这里工作是为了解决如何将我的timezoneoffset转换为时区字符串,以便在SQL Server 2008中将日期转换为DATETIMEOFFSET的问题。但很必要。

因此,我需要一种可以处理负数和正数的方法,如果需要,可以将它们格式化为以零开头的两个字符。Anons的答案使我很接近,但时区值为负,因为0-5而不是必需的值-05

因此,对他的答案进行了一些调整,该方法适用于所有时区小时转换

DECLARE @n INT = 13 -- Works with -13, -5, 0, 5, etc
SELECT CASE 
    WHEN @n < 0 THEN '-' + REPLACE(STR(@n * -1 ,2),' ','0') 
    ELSE '+' + REPLACE(STR(@n,2),' ','0') END + ':00'

-1

我创建了此函数,该函数可满足bigint和一个前导零或其他单个字符(最多返回20个字符)的要求,并且允许结果的长度小于输入数字的长度:

create FUNCTION fnPadNum (
  @Num BIGINT --Number to be padded, @sLen BIGINT --Total length of results , @PadChar varchar(1))
  RETURNS VARCHAR(20)
  AS
  --Pads bigint with leading 0's
            --Sample:  "select dbo.fnPadNum(201,5,'0')" returns "00201"
            --Sample:  "select dbo.fnPadNum(201,5,'*')" returns "**201"
            --Sample:  "select dbo.fnPadNum(201,5,' ')" returns "  201"
   BEGIN
     DECLARE @Results VARCHAR(20)
     SELECT @Results = CASE 
     WHEN @sLen >= len(ISNULL(@Num, 0))
     THEN replicate(@PadChar, @sLen - len(@Num)) + CAST(ISNULL(@Num, 0) AS VARCHAR)
     ELSE CAST(ISNULL(@Num, 0) AS VARCHAR)
     END

     RETURN @Results
     END
     GO

     --Usage:
      SELECT dbo.fnPadNum(201, 5,'0')
      SELECT dbo.fnPadNum(201, 5,'*')
      SELECT dbo.fnPadNum(201, 5,' ')
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.