繁体   English   中英

如何从右侧每 3 个字符将一个字符插入字符串

[英]How to insert a character into a string every 3 characters from the right

我有一个由数字组成的字符串。 字符串的长度范围从 1 个字符到 9 个字符。 我想从右边每三个字符插入一个破折号 (-)。 这仅与具有三个以上字符的字符串相关。 这只是一个 select 语句,因为我不想实际更新字符串本身。

例如,

8 should return 8
476 should return 476
4767 should return 4-767
45907392 should return 45-907-392
845907392 should return 845-907-392

这应该有效:

select 
  *,
  replace(format(n,'#,#'),',','-')
from (values (8),(476),(4767),(45907392),(845907392)) x (n)

改成。 如果它在您的系统中是千位分隔符,或者在 FORMAT function 中提供文化作为第三个参数,所以它总是一样的。

由于 SQL Server 2012 您可以使用FORMAT function ,如其他答案中所述。 如果您也想格式化像“abcde”这样的字符串值,您只能使用这样的字符串函数:

DECLARE @str VARCHAR(100) = '845907392';

-- 845-907-392
SELECT REVERSE(SUBSTRING(REVERSE(@str), 7, 3)) 
  + CASE WHEN LEN(@str)>6 THEN '-' ELSE '' END 
  + REVERSE(SUBSTRING(REVERSE(@str), 4, 3)) 
  + CASE WHEN LEN(@str)>3 THEN '-' ELSE '' END 
  + REVERSE(SUBSTRING(REVERSE(@str), 1, 3))

您还可以创建 function:

CREATE FUNCTION dbo.GetFormatTripleDash (@str varchar(255))
RETURNS VARCHAR(255)
AS
BEGIN
  DECLARE @retStr VARCHAR(255) = REVERSE(SUBSTRING(REVERSE(@str), 7, 3)) 
    + CASE WHEN LEN(@str)>6 THEN '-' ELSE '' END 
    + REVERSE(SUBSTRING(REVERSE(@str), 4, 3)) 
    + CASE WHEN LEN(@str)>3 THEN '-' ELSE '' END 
    + REVERSE(SUBSTRING(REVERSE(@str), 1, 3))
  RETURN(@retStr)
END

你可以像这样使用这个函数:

-- 845-907-392
SELECT dbo.GetFormatTripleDash('845907392')

使用 function 的更灵活的解决方案。 现在您可以使用更长的字符串值,并且可以定义由-字符分隔的零件大小。

CREATE FUNCTION dbo.GetFormatDash (@str varchar(255), @partSize INT = 3)
RETURNS VARCHAR(255)
AS
BEGIN
  DECLARE @startSize INT = 0;
  DECLARE @retStr VARCHAR(255) = '';

  WHILE @startSize < LEN(@str)
  BEGIN
    SET @retStr = REVERSE(SUBSTRING(REVERSE(@str), @startSize + 1, @partSize)) + CASE WHEN @startSize > 0 THEN '-' ELSE '' END + @retStr;
    SET @startSize = @startSize + @partSize;
  END

  RETURN(@retStr)
END 

您可以像这样使用这个改进的 function:

-- 12-345-678-901-234-567-890
SELECT dbo.GetFormatDash('12345678901234567890', DEFAULT)
SELECT dbo.GetFormatDash('12345678901234567890', 3)

-- 12345-67890-12345-67890
SELECT dbo.GetFormatDash('12345678901234567890', 5)

dbfiddle.uk 上的演示

使用format() function 试试这个。

Select Replace(format(8, '#,##0'), ',', '-')
Select Replace(format(476, '#,##0'), ',', '-')
Select Replace(format(45907392, '#,##0'), ',', '-')
Select Replace(format(845907392, '#,##0'), ',', '-')

现场db<>fiddle演示。

在此处输入图像描述

它有点恶心,但它的工作原理! 试试看,如果你同意,请告诉我

    SELECT
        CASE    
            WHEN LEN(yourColumn)>6 THEN format(CAST(YourColumn AS NUMERIC), '###-###-###') 
            WHEN LEN(YourColumn)>3 THEN format(CAST(YourColumn AS NUMERIC), '###-###')
            ELSE YourColumn
        END

这是另一种方法,尽管输入更多

    SELECT
        CASE    
            WHEN LEN(yourColumn)>6 THEN SUBSTRING(YourColumn, 1, 3) +'-'+ SUBSTRING(YourColumn, 4, 3)
            WHEN LEN(YourColumn)>3 THEN REVERSE(SUBSTRING(REVERSE(YourColumn), 1, 3) +'-'+ SUBSTRING(REVERSE(YourColumn), 4, 3))
            ELSE YourColumn
        END         

尝试这个。 我相信它也可以通过一些努力进行扩展以允许任意数量的字符

declare @input nvarchar(100) = '845907392'
declare @separator char(1) = '-'

--option1 - CTE

;with dash1 as (
    select isnull(stuff(reverse(@input), 1+3, 0, @separator), reverse(@input)) as v
)
, dash2 as(
    select isnull(stuff(v, 1+7, 0, @separator), v) as v from dash1
)
select reverse(v) from dash2


--option2 - Non CTE
select reverse(isnull(stuff(isnull(stuff(reverse(@input), 1+3, 0, @separator), reverse(@input)), 1+7, 0, @separator), isnull(stuff(reverse(@input), 1+3, 0, @separator), reverse(@input))))

具有递归 CTE 的解决方案:

with cte as (
  select col, len(col) - 3 pos from tablename
  union all 
  select 
    cast(left(col, pos) + '-' + right(col, len(col) - pos) as varchar(100)), 
    pos - 3
  from cte
  where pos > 0
)
select col from cte
where pos <= 0

演示
结果:

> | col         |
> | :---------- |
> | 8           |
> | 476         |
> | 845-907-392 |
> | 45-907-392  |
> | 4-767       |

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM