【问题标题】:Replace email inside varchar tsql替换 varchar sql 中的电子邮件
【发布时间】:2017-08-13 11:27:42
【问题描述】:

我在列中的字符串化 JSON 中有一个电子邮件地址。

我需要用其他电子邮件地址替换它。

我应该补充一点,我不能为此使用 CLR。那太容易了。

我会接受其他建议,但我想出的最佳方法是替换 @ 之前和之后的 "s 之间的所有内容。

DECLARE @testEmailAddress varchar(255);
SET @testEmailAddress = 'MyReplacementEmail@gmail.com'; 
UPDATE #TestEmails
SET 
    COMM_DATA = 
        STUFF (
            COMM_DATA,      
            PATINDEX(
                '%@%', 
                COMM_DATA
            ) 
            -
            PATINDEX ('%"%',
                REVERSE(
                    SUBSTRING(
                        COMM_DATA, 
                        0, 
                        PATINDEX(
                            '%@%', 
                            COMM_DATA
                        )
                    )
                )
            ) + 1,
            PATINDEX(
                '%@%', 
                COMM_DATA
            ) 
            +
            PATINDEX ('%"%',
                SUBSTRING(
                    COMM_DATA, 
                    PATINDEX(
                        '%@%', 
                        COMM_DATA
                    ),
                    LEN(COMM_DATA)
                )
            ) - 1,
            @testEmailAddress
        )
;

这几乎可行,只是替换电子邮件地址似乎超出了替换字符串几个字符。

例如

{"CustomerEmail":"original@test.com","property2":"value2","property3":"value3","property4":"value4","property5":"value5","property6":"value6","property7":"value7","property8":"value8"}

变成

{"CutomerEmail":"MyReplacementEmail@gmail.comproperty8":"value8"}

但我希望它是

{"CustomerEmail":"MyReplacementEmail@gmail.com","property2":"value2","property3":"value3","property4":"value4","property5":"value5","property6":"value6","property7":"value7","property8":"value8"}

【问题讨论】:

  • 您的'becomes' 是错误的结果还是您想要的结果?
  • @JuanCarlosOropeza 错误的结果。我会澄清并发布我的期望。
  • 为什么在"CustomerEmail":之后没有找到"的第一次出现?
  • JSON 在记录间不一致。我可以肯定地说,只有一个电子邮件地址(并且只有一个@),所以我将其作为搜索的起点。
  • 但是有多少个"CustomerEmail":?这是sql server?

标签: sql tsql replace


【解决方案1】:

我会做更多这样的事情:虽然我打赌在 SQL 2016 中,有比普通字符串解析更好的查询和替换数据的方法。

DECLARE @replace varchar(255) = '"MyReplacementEmail@gmail.com"'; 

DECLARE @JSON VARCHAR(4000) = '{"CustomerEmail":"original@test.com","property2":"value2","property3":"value3","property4":"value4","property5":"value5","property6":"value6","property7":"value7","property8":"value8"}'

DECLARE @Search VARCHAR(128) = '"CustomerEmail"'

DECLARE
    @SearchStart  INT
,   @SearchEnd    INT
,   @ValStart     INT
,   @ValEnd       INT
;

SELECT 
    @SearchStart = CHARINDEX(@Search, @JSON, 1) 
,   @SearchEnd = CHARINDEX(@Search, @JSON, 1) + LEN(@Search) 
,   @ValStart = CHARINDEX(':', @JSON, CHARINDEX(@Search, @JSON, 1) + LEN(@Search)) + 1 
,   @ValEnd = CHARINDEX('"', @JSON, CHARINDEX(@Search, @JSON, 1) + LEN(@Search) + 2) + 1 

SELECT STUFF(@Json, @ValStart, @ValEnd - @ValStart, @replace)

我基本上可以使它成为一个标量函数,它接受一个字符串(varchar JSON)并返回一个改变的 JSON。您本质上只是在字符串中寻找密钥对。这样,我可以针对结果集运行它并执行 N 次,并且只需要我正在搜索的字段的参数(@JSON),我正在搜索要替换的“关键”(@CustomerEmail),以及我用什么替换它(@replace)。

【讨论】:

    【解决方案2】:

    CROSS APLLY 对于这样的计算很方便

    declare @t table (comm_data varchar(max))
    insert @t values
    ('{"CustomerEmail":"original@test.com","property2":"value2","property3":"value3","property4":"value4","property5":"value5","property6":"value6","property7":"value7","property8":"value8"}');
    
    DECLARE @testEmailAddress varchar(255);
    SET @testEmailAddress = 'MyReplacementEmail@gmail.com'; 
    select t1.*, t2.*, stuff(comm_data,p1-p2+2,p2+p3-3,@testEmailAddress)
    from @t 
    cross apply (
         select p1=PATINDEX('%@%',COMM_DATA)
        ) t1
    cross apply (
         select p2=PATINDEX('%":"%', reverse(left(COMM_DATA,p1))),
           p3 = PATINDEX('%","%', substring(COMM_DATA, p1, len(COMM_DATA)))
        ) t2
    

    您可以轻松调试正确的 p1-p2+2,p2+p3-3 stuff 边界,并在需要时将代码转换为长格式。

    【讨论】:

      【解决方案3】:

      我误算了终点。我没有给出STUFF 的起点和终点之间的距离,而是给出了字符串开头的起点和终点位置。最终代码如下:

          COMM_DATA = 
              STUFF (
                  COMM_DATA,      
                  PATINDEX(
                      '%@%', 
                      COMM_DATA
                  ) 
                  -
                  PATINDEX ('%"%',
                      REVERSE(
                          SUBSTRING(
                              COMM_DATA, 
                              0, 
                              PATINDEX(
                                  '%@%', 
                                  COMM_DATA
                              )
                          )
                      )
                  )+ 1,
                  PATINDEX(
                      '%@%', 
                      COMM_DATA
                  ) 
                  +
                  PATINDEX ('%"%',
                      SUBSTRING(
                          COMM_DATA, 
                          PATINDEX(
                              '%@%', 
                              COMM_DATA
                          ),
                          LEN(COMM_DATA)
                      )
                  )
                  -
                  (
                      PATINDEX(
                          '%@%', 
                          COMM_DATA
                      ) 
                      -
                      PATINDEX ('%"%',
                          REVERSE(
                              SUBSTRING(
                                  COMM_DATA, 
                                  0, 
                                  PATINDEX(
                                      '%@%', 
                                      COMM_DATA
                                  )
                              )
                          )
                      )
                  ) - 2,
                  @testEmailAddress
              )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-28
        • 1970-01-01
        • 2017-12-11
        • 1970-01-01
        • 1970-01-01
        • 2013-08-29
        相关资源
        最近更新 更多