【问题标题】:Replace strings between two characters using T-SQL使用 T-SQL 替换两个字符之间的字符串
【发布时间】:2021-01-20 03:57:13
【问题描述】:

我需要更新一个字符串来修改任何别名——可以是“H1.”、“H2.”、“H3.”...等等——全部为“S”。并且正在努力找出逻辑。 例如我有这个:

'H1.HUB_CUST_ID、H2.HUB_SALE_ID、H3.HUB_LOC_ID'

但我想要这个:

'S.HUB_CUST_ID、S.HUB_SALE_ID、S.HUB_LOC_ID'

如果你可以在 REPLACE 中使用通配符,我会做这样的事情 REPLACE(@string, 'H%.H', 'S.H')。

理论上,可以有多少个 H# 别名是没有限制的。实际上,几乎肯定会少于 10 个。

有没有比单独嵌套替换 H1 - H10 更好的方法,这在脚本中看起来很乱,如果将来连接更多表,风险很小?

【问题讨论】:

  • 这在 SQL Server 中很难实现,它基本上不支持正则表达式。我投票赞成首先规范化您的数据,然后在数据库之外处理此要求。
  • 谢谢蒂姆。我已经对其进行了编辑以简化我的问题,但实际上该字符串是一个长 SQL 脚本,除了这些别名之外几乎完全符合要求 - 所以规范化在这里并不真正适用。
  • @JShark 在这种情况下,最好使用除 T-SQL 之外的任何其他工具。应该没有任何理由实时执行此类转换,您应该能够更早地生成正确的脚本。您可以使用 Powershell 来构建它并使用正则表达式进行替换、小型 C# 程序或编辑器的正则表达式替换功能

标签: sql sql-server replace sql-server-2014


【解决方案1】:

SQL Server 不支持模式替换。您最好使用不同的语言,它支持模式/REGEX 替换或实现 CLR 函数。

话虽如此,但考虑到您说该值始终低于 10,您可以强行使用它,但它并不“漂亮”。

SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(YourString,'H1.','S.'),'H2.','S.'),'H3.','S.'),'H4.','S.'),'H5.','S.'),'H6.','S.'),'H7.','S.'),'H8.','S.'),'H9.','S.')
FROM YourTable ...

【讨论】:

    【解决方案2】:

    您可以将您的字符串转换为 XML,然后将其转换为简单的表格:

    DECLARE @txt nvarchar(max) = N'H1.HUB_CUST_ID, H2.HUB_SALE_ID, H3.HUB_LOC_ID',
            @x xml 
    
    SELECT @x = '<a al="' + REPLACE(REPLACE(@txt,', ','</a><a al="'),'.','">')+ '</a>'
    
    SELECT t.c.value('@al', 'nvarchar(max)') as alias_name,
           t.c.value('.','nvarchar(max)') as col_name
    FROM @x.nodes('/a') t(c)
    

    输出:

    alias_name   col_name
    H1           HUB_CUST_ID
    H2           HUB_SALE_ID
    H3           HUB_LOC_ID
    

    您可以将结果放入临时表,使用LIKE 'some basic pattern' 修改它们,然后构建新字符串。

    【讨论】:

      【解决方案3】:

      如果你不关心结果顺序,你可以取消聚合和重新聚合:

      select t.*, v.new_val
      from t cross apply
           (select string_agg(concat('S1', stuff(s.value, 1, charindex('.'), '') - 1, ',') within group (order by (select null) as newval
            from string_split(t.col, ',') s
           ) s;
      

      注意:这假定所有值都以您要替换的前缀开头——正如您的示例数据所暗示的那样。如果有异常,可以使用case 表达式。

      您实际上可以使用charindex() 获得原始排序(假设没有重复):

      select t.*, v.new_val
      from t cross apply
           (select string_agg(concat('S1', stuff(s.value, 1, charindex('.'), '') - 1, ',')
                               within group (order by charindex(s.value, t.col)
                             ) as newval
            from string_split(t.col, ',') s
           ) s;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-13
        • 1970-01-01
        • 2020-11-05
        • 2018-02-10
        • 2011-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多