【问题标题】:SQL UPDATE specific characters in stringSQL UPDATE 字符串中的特定字符
【发布时间】:2017-05-10 07:50:16
【问题描述】:

我有一列包含以下值(还有很多):

20150223-001
20150224-002
20150225-003

我需要编写一个 UPDATE 语句,它将破折号后的前 2 个字符更改为“AB”。结果必须如下:

 20150223-AB1
 20150224-AB2
 20150225-AB3

谁能帮我解决这个问题?

提前致谢。

【问题讨论】:

  • 破折号前是否总是 8 个字符?然后就可以使用 substring 和 concat 了。
  • 看看能不能帮到你。 stackoverflow.com/questions/9260044/…
  • 是的,破折号前总是有 8 个字符,但破折号后的字符可能会有所不同。它必须在破折号之后更新前两个。
  • 如果输入是20150223-00001,那么预期的输出是什么? 20150223-AB001,或20150223-ABCD1,??
  • 20170123-01520170123-123 这样的值呢,这些也会出现吗?又该如何处理?

标签: sql sql-server


【解决方案1】:

使用这个,

DECLARE @MyString VARCHAR(30) = '20150223-0000000001'

SELECT STUFF(@MyString,CHARINDEX('-',@MyString)+1,2,'AB')

【讨论】:

    【解决方案2】:

    如果数据量很大,可以考虑使用.WRITE子句。但仅限于VARCHAR(MAX)NVARCHAR(MAX)VARBINARY(MAX) 数据类型。

    如果您有以下列类型之一,.WRITE 子句最容易达到此目的,示例如下:

    UPDATE Codes
    SET val.WRITE('AB',9,2)
    GO
    

    其他可能的选择可能很简单REPLACE:

    UPDATE Codes
    SET val=REPLACE(val,SUBSTRING(val,10,2),'AB')
    GO
    

    STUFF:

    UPDATE Codes
    SET val=STUFF(val,10,2,'AB')
    GO
    

    我基于该列中始终有 8 个日期字符和一个破折号的信息。我准备了一张表格并检查了这里提到的一些解决方案。

    CREATE TABLE Codes(val NVARCHAR(MAX))
    
    INSERT INTO Codes
    SELECT TOP 500000 CONVERT(NVARCHAR(128),GETDATE()-CHECKSUM(NEWID())%1000,112)+'-00'+CAST(ABS(CAST(CHECKSUM(NEWID())%10000 AS INT)) AS NVARCHAR(128))
    FROM sys.columns s1 CROSS JOIN sys.columns s2
    

    我运行了一些测试,基于 NVARCHAR(MAX) 列的 10kk 行,我得到了以下结果:

    +---------+------------+
    | Method  |    Time    |
    +---------+------------+
    | .WRITE  | 28 seconds |
    | REPLACE | 30 seconds |
    | STUFF   | 15 seconds |
    +---------+------------+
    

    正如我们所见,STUFF 看起来是更新部分字符串的最佳选择。 .WRITE 应在您将新数据插入或追加到字符串时考虑,然后如果数据库恢复模型设置为批量记录或简单,则可以利用最小日志记录。根据MSDN文章关于UPDATE声明:Updating Large Value Data Types

    【讨论】:

      【解决方案3】:

      根据 OP 评论:-

      破折号前总是 8 个字符,但后面的字符 破折号可能会有所不同。它必须在破折号之后更新前两个。

      使用下一个简单的代码:-

      DECLARE @MyString VARCHAR(30) = '20150223-0000000001'
      
      SELECT REPLACE(@MyString,SUBSTRING(@MyString,9,3),'-AB')
      

      结果:-

      20150223-AB00000001
      

      【讨论】:

      • 如果相同的字符序列也可以出现在其他位置以及,则存在风险。这将替换所有实例,而不仅仅是出现在位置 9-11 的实例。
      • 你是对的,最终代码是根据OP的要求创建的。
      【解决方案4】:

      试试,

      update table set column=stuff(column,charindex('-',column)+1,2,'AB')
      

      【讨论】:

      • 如果输入为20150223-0000000001,则它不起作用,请检查我的答案?
      【解决方案5】:
      Declare @Table1 TABLE (DateValue Varchar(50))
      INSERT INTO @Table1
      SELECT '20150223-000000001' Union all
      SELECT '20150224-000000002' Union all
      SELECT '20150225-000000003'
      
      SELECT DateValue,
      CONCAT(SUBSTRING(DateValue,0,CHARINDEX('-',DateValue)),
      REPLACE(LEFT(SUBSTRING(DateValue,CHARINDEX('-',DateValue)+1,Len(DateValue)),2),'00','-AB'),
      SUBSTRING(DateValue,CHARINDEX('-',DateValue)+1,Len(DateValue))) AS ExpectedDateValue
      FROM @Table1
      

      输出

         DateValue                ExpectedDateValue
      ---------------------------------------------
         20150223-000000001   20150223-AB000000001
         20150224-000000002   20150224-AB000000002
         20150225-000000003   20150225-AB000000003
      

      更新

      Update @Table1
      SEt DateValue= CONCAT(SUBSTRING(DateValue,0,CHARINDEX('-',DateValue)),
      REPLACE(LEFT(SUBSTRING(DateValue,CHARINDEX('-',DateValue)+1,Len(DateValue)),2),'00','-AB'),
      SUBSTRING(DateValue,CHARINDEX('-',DateValue)+1,Len(DateValue)))
      From @Table1
      
      SELECT * from @Table1
      

      输出

          DateValue
         -------------
      20150223-AB000000001
      20150224-AB000000002
      20150225-AB000000003
      

      【讨论】:

      • 如果输入为20150223-0000000001,则无法正常工作,请检查我的答案?
      • 谢谢,我只是更改了我的代码,它适用于上述数据,前面还有更多的零
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-14
      • 2017-07-11
      相关资源
      最近更新 更多