【问题标题】:SQL replace every other comma with a semicolonSQL 用分号替换所有其他逗号
【发布时间】:2014-03-26 14:20:46
【问题描述】:

我有一堆字符串应该存储为值对,但没有。现在我需要用分号替换所有其他逗号以使它们成对。希望找到一种简单的方法来做到这一点,但可能没有。

例如:

-1328.89,6354.22,-1283.94,6242.96,-1172.68,6287.91,-1217.63,6399.18

应该是:

-1328.89,6354.22;-1283.94,6242.96;-1172.68,6287.91;-1217.63,6399.18

【问题讨论】:

  • 所有的数字都是负数还是仅仅因为你的具体例子?
  • 你的意思是每隔一个逗号,还是每隔一个逗号?
  • 您有一个包含单个 VarChar 列的数据库,其中包含诸如“-1328.89,6354.22,-1283.94,6242.96,...”之类的字符串?你有比“其他逗号”更大的问题;您的数据违反了第一范式。您需要将列拆分为多行,每行一个值。
  • BWS-是的,每隔一个逗号,抱歉,修复“应该是”值
  • 我为你的表格结构哭泣。你肯定需要改变你的数据库存储数据的方式,因为这是一团糟。

标签: sql sql-server replace


【解决方案1】:
create function f_tst(@a varchar(100)) -- use right size of field
returns varchar(100) -- make sure you use the right size of field
begin
declare @pos int = charindex(',', @a) + 1
;while 0 < charindex(',', @a, @pos) 
select @a = stuff(@a, charindex(',', @a, @pos), 1, ';'), 
@pos = charindex(',', @a, charindex(',', @a, @pos + 1)) + 1

return @a
end

go

declare @a varchar(100) = '-1328.89,6354.22,-1283.94,6242.96,-1172.68,6287.91,-1217.63,6399.18'
select dbo.f_tst(@a)

或者在你的例子中

update <table>
set <field> = dbo.f_tst(<field>)

【讨论】:

  • 很棒的解决方案,使用最少的代码行,这是我一直在寻找的“简单”解决方案。谢谢!
【解决方案2】:

当然不是你想要的那么简单,而是一个 CHARINDEX/SUBSTRING 解决方案:

Declare @input nvarchar(max) = '-1328.89,6354.22,-1283.94,6242.96,-1172.68,6287.91,-1217.63,6399.18'

Declare @i int = 0, @t int = 0, @isComma bit = 1
Declare @output nvarchar(max) = ''
Select @i = CHARINDEX(',', @input)
While (@i > 0)
Begin
    Select @output = @output + SUBSTRING(@input, @t + 1, @i - @t - 1) + CASE @isComma WHEN 1 THEN ',' ELSE ';' END
    Select @t = @i
    Select @i = CHARINDEX(',', @input, @i + 1), @isComma = 1 - @isComma
End
Select @output = @output + SUBSTRING(@input, @t + 1, 1000)
Select @output

【讨论】:

    【解决方案3】:

    这可以通过动态 sql 和 for xml 的组合来完成:

    declare @sql nvarchar(max)
    set @sql = '-1328.89,6354.22,-1283.94,6242.96,-1172.68,6287.91,-1217.63,6399.18'
    set @sql = '
        select replace((select cast(value as varchar(50)) +
        cast(case row_number() over(order by sort)%2 when 0 then '','' else '';'' end as char(1))
        from (select ' + replace(@sql,',',' value,1 sort union all select ') + ',1 sort)q
        for xml path(''''))+''||'','',||'','''') YourUpdatedValue'
    exec(@sql)
    

    【讨论】:

      【解决方案4】:

      这可以在单个查询中完成:

      DECLARE @t TABLE (id int, col varchar(max))
      INSERT @t VALUES
      (1,'-1328.89,6354.22,-1283.94,6242.96,-1172.68,6287.91,-1217.63,6399.18'),
      (2,'-4534.89,454.22,-1123.94,2932.96,-1872.68,327.91,-417.63,635.18')
      
      ;WITH t AS (
        SELECT id, i % 2 x, i / 2 y, val
        FROM @t
        CROSS APPLY (SELECT CAST('<a>'+REPLACE(col,',','</a><a>')+'</a>' AS xml) xml1 ) t1
        CROSS APPLY (
          SELECT
            n.value('for $i in . return count(../*[. << $i])', 'int') i,
            n.value('.','varchar(max)') AS val
          FROM xml1.nodes('a') x(n)
        ) t2
      )
      SELECT id, y, [0]+','+[1] col
      FROM t
      PIVOT(MAX([val]) FOR x IN ([0],[1])) t3
      ORDER BY id, y
      
      
      id  y   val
      ----------------------------
      1   0   -1328.89,6354.22
      1   1   -1283.94,6242.96
      1   2   -1172.68,6287.91
      1   3   -1217.63,6399.18
      2   0   -4534.89,454.22
      2   1   -1123.94,2932.96
      2   2   -1872.68,327.91
      2   3   -417.63,635.18
      

      【讨论】:

      • 感谢 Anon,如果我们决定将数据拆分到另一个表中,这将是完美的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 2017-06-20
      • 1970-01-01
      相关资源
      最近更新 更多