如何在SQL中将零填充到子字符串?

时间:2017-11-29 19:02:39

标签: sql sql-server

我有一个varchar类型列,其文本类似于20171126-401-9-4496。 该字符串有4个部分,每个部分都有固定的长度:

第1节--8位数

第2节--4位数

第3节 - 2位数

第4节--4位

我想用' 0'填充字符串的第2和第3部分,以便文本变为 20171126-0401-09-4496满足每个部分的固定长度要求。我尝试使用SUBSTRINGCHARINDEX函数,但无法获得所需的结果。如何解决这个问题?

5 个答案:

答案 0 :(得分:6)

PARSENAME黑客的完美时间!

SELECT PARSENAME(REPLACE(MyColumn,'-','.'),4)+'-'+
       RIGHT('0000'+PARSENAME(REPLACE(MyColumn,'-','.'),3),4)+'-'+
       RIGHT('00'+PARSENAME(REPLACE(MyColumn,'-','.'),2),2)+'-'+
       PARSENAME(REPLACE(MyColumn,'-','.'),1)

答案 1 :(得分:1)

如果您总是希望在这些位置上插入'0',那么它将起作用:

select stuff (stuff('20171126-401-9-4496',14,0,0),10,0,'0')

enter image description here

如果我们有一个可变长度的字段,那么它将像这样工作(第一个字段的例子):

select @str = '20175555-0001-9-46'

select @len =  (select charindex('-',substring(@str,10,100)))

select
case 
when @len = 2 
then stuff(@str,10,0,'000')
when @len = 3 
then stuff(@str,10,0,'00')
when @len = 4 
then stuff(@str,10,0,'0')
else
@str
end as string

答案 2 :(得分:1)

接受Tab Allemen所做的事情,您也可以将它应用于第一列和最后一列......

declare @var varchar(18) = '201711-1-9-4496'


SELECT right('00000000' + parsename(replace(@var,'-','.'),4),8) + '-'
        + right('0000' + parsename(replace(@var,'-','.'),3),4) + '-'
        + right('00' + parsename(replace(@var,'-','.'),2),2) + '-'
        + right('0000' + parsename(replace(@var,'-','.'),1),4) 

答案 3 :(得分:0)

如果你真的喜欢派生表...

DECLARE @mytable TABLE (mynewstring varchar(100)) --replace @mytable with your table name

INSERT INTO @mytable VALUES 
 ('20171126-401-9-4496')
,('1-401-9-4496')
,('1-1-1-1')
,('---')

SELECT dT4.FirstVal + SecondVal + ThirdVal + FourthVal [newval]
  FROM (
SELECT LEFT('00000000', len('00000000') - (dT3.[firstD] - 1)) + LEFT(mynewstring, [firstD]) [FirstVal]
      ,LEFT('0000', len('0000') - ([secondD] - [firstD] - 1)) + SUBSTRING(mynewstring, [firstD] + 1, [secondD] - [firstD]) [SecondVal]
      ,LEFT('00', len('00') - ([thirdD] - [secondD] - 1)) + SUBSTRING(mynewstring, [secondD] + 1, [thirdD] - [secondD]) [ThirdVal]
      ,LEFT('0000', len('0000') - (len(mynewstring) - [thirdD])) + SUBSTRING(mynewstring, [thirdD] + 1, len(mynewstring) - [thirdD]) [FourthVal]
  FROM (
SELECT dT2.*
      ,CHARINDEX('-', dT2.mynewstring, dT2.[secondD] + 1) [thirdD]
  FROM (
SELECT dT.*
      ,CHARINDEX('-', dT.mynewstring, dT.[firstD]+1) [secondD]
  FROM (
SELECT mynewstring  
      ,CHARINDEX('-', mynewstring, 0) [firstD]    
  FROM @mytable
       ) AS dT      
       ) AS dT2
       ) AS dT3
       ) AS dT4

会产生输出:

newval
20171126-0401-09-4496
00000001-0401-09-4496
00000001-0001-01-0001
00000000-0000-00-0000

该算法依次抓取破折号的位置。然后它为该位置进行0和字符串连接。最后,这些值被连接起来。

答案 4 :(得分:0)

要圆滑并显示一个拆分字符串方法,以防有人看到这个问题,并且当parsename hack无法工作时有5个或更多部分。

DECLARE @Table AS TABLE (col1 VARCHAR(50))
INSERT INTO @Table VALUES
    ('20171127-4301-9-4496'),('20171125-301-9-4496'),('20171124-21-9-4496'),('20171123-1-9-4496'),('20171122-1-09-4496')

SELECT
    *
    ,NewFormat = p1 + '-' + RIGHT('0000' + P2, 4) + '-' + RIGHT('00' + P3,2) + '-' + P4
FROM
    (
       SELECT col1, xmlcol1 = CAST(('<row><col>' + REPLACE(col1,'-','</col><col>') + '</col></row>') AS XML)
       FROM
          @Table 
    ) t
    CROSS APPLY
       (SELECT
          t.n.value('col[1]','VARCHAR(50)') as P1
          ,t.n.value('col[2]','VARCHAR(50)') as P2
          ,t.n.value('col[3]','VARCHAR(50)') as P3
          ,t.n.value('col[4]','VARCHAR(50)') as P4
        FROM
          t.xmlcol1.nodes ('/row') AS t(n)) c

你也可以进行扩展,这样你就可以测试字符串的部分是否有超过4个字符等,而不是填充它或者什么都没有。