【问题标题】:Replace duplicate spaces with a single space in T-SQL用 T-SQL 中的单个空格替换重复的空格
【发布时间】:2011-01-28 04:25:33
【问题描述】:

我需要确保给定字段的字符之间不包含多个空格(我不关心所有空格,只是空格)。

所以

'single    spaces   only'

需要变成

'single spaces only'

下面的行不通

select replace('single    spaces   only','  ',' ')

因为它会导致

'single  spaces  only'

我真的更愿意坚持使用原生 T-SQL,而不是基于 CLR 的解决方案。

想法?

【问题讨论】:

标签: sql-server tsql


【解决方案1】:

更整洁:

select string = replace(replace(replace(' select   single       spaces',' ','<>'),'><',''),'<>',' ')

输出:

选择单个空格

【讨论】:

  • 如果你想删除字符串前面和结尾的空格,然后将替换包装在 LTRIM 中,RTRIM 它将为你完成。
  • 只要你的字符串不包含很多 符号。根据我的喜好,似乎很脆弱。
  • 真正优雅的 hack。赞成。如果 可能在输入文本中,则任何两个字符都可以用于中间部分。
  • 克里斯,您可以使用不可打印的 ASCII 字符,例如 CHAR(17) 和 CHAR(18),因为这些字符永远不会出现在您的输入文本中。仍然比循环接受的答案更快。
  • 我不得不仔细观察一下,才能知道您使用了 '>
【解决方案2】:

这可行:

declare @test varchar(100)
set @test = 'this   is  a    test'

while charindex('  ',@test  ) > 0
begin
   set @test = replace(@test, '  ', ' ')
end

select @test

【讨论】:

  • 封装函数并将 varchar(100) 更改为 nvarchar(max)
  • James 和 Neil 的脚本之间的区别在于 James 运行 while 循环,根据个人经验,让它运行一个表的 50,000 条记录往往非常慢,因此您需要将其创建为程序并传递一个记录和一些你可能没有权限创建一个带新程序的工作。 Neil 使用每个现有的函数,因为它使用 ,如果你有一个像 "release &lt; now" 这样的字符串,那么你会得到 "release&lt;&gt;&lt;&gt;&lt;&lt;&gt;&lt;&gt;now""release&lt;&lt;&gt;now""release&lt; now",它与任何一对符号相同,如果你有一对中的一个然后它会移动
  • 运行 50k 条记录应该很快,如果这是您的问题,我会调查其他问题。
【解决方案3】:

这有点蛮力,但会奏效

CREATE FUNCTION stripDoubleSpaces(@prmSource varchar(max)) Returns varchar(max)
AS 
BEGIN
    WHILE (PATINDEX('%  %', @prmSource)>0)
     BEGIN
        SET @prmSource = replace(@prmSource  ,'  ',' ')
     END

    RETURN @prmSource
END

GO

-- Unit test -- 
PRINT dbo.stripDoubleSpaces('single    spaces   only')

single spaces only

【讨论】:

    【解决方案4】:

    如果您知道一行中的空格数不会超过一定数量,则可以嵌套替换:

    replace(replace(replace(replace(myText,'  ',' '),'  ',' '),'  ',' '),'  ',' ')
    

    4 次替换应最多修复 16 个连续空格(16,然后 8,然后 4,然后 2,然后 1)

    如果它可以显着延长,那么您将不得不执行类似内联函数的操作:

    CREATE FUNCTION strip_spaces(@str varchar(8000))
    RETURNS varchar(8000) AS
    BEGIN 
        WHILE CHARINDEX('  ', @str) > 0 
            SET @str = REPLACE(@str, '  ', ' ')
    
        RETURN @str
    END
    

    那就做吧

    SELECT dbo.strip_spaces(myText) FROM myTable
    

    【讨论】:

    • 布拉德,我的代码几乎相同,但你打败了我,所以点赞。多次 REPLACE() 调用是骇人听闻的,但如果预期的“额外”空间的数量是可预测的并且相对较小,它会做得很好并且满足 OP 的要求,不通过 CLR 调用 RegEx 代码。
    【解决方案5】:
    update mytable
    set myfield = replace (myfield, '  ',  ' ')
    where charindex('  ', myfield) > 0 
    

    替换将适用于所有双空格,无需进行多次替换。这是基于集合的解决方案。

    【讨论】:

    • 这不是将 4 个空格合并为 2 个吗?
    • 我在我的问题中称这个解决方案不符合需求,但谢谢。
    • 我同意 OP 的观点,即这不能回答问题;这无法在一次点击中将 3+ 个空格减少到 1 个。标记为 NAA
    【解决方案6】:

    这是通过多次替换的解决方案,适用于任何字符串(不需要特殊字符,它们不是字符串的一部分)。

    declare @value varchar(max)
    declare @result varchar(max)
    set @value = 'alpha   beta gamma  delta       xyz'
    
    set @result = replace(replace(replace(replace(replace(replace(replace(
      @value,'a','ac'),'x','ab'),'  ',' x'),'x ',''),'x',''),'ab','x'),'ac','a')
    
    select @result -- 'alpha beta gamma delta xyz'
    

    【讨论】:

    • 好东西,但将“abe”更改为“axe”
    • 与接受的答案相同,请不要发布重复的答案;我们不再需要 SO 上的噪音了
    【解决方案7】:

    在寻找答案时发现了这个:

    SELECT REPLACE(
            REPLACE(
                 REPLACE(
                    LTRIM(RTRIM('1 2  3   4    5     6'))
                ,'  ',' '+CHAR(7))
            ,CHAR(7)+' ','')
        ,CHAR(7),'') AS CleanString
    where charindex('  ', '1 2  3   4    5     6') > 0
    

    完整答案(附解释)来自:http://techtipsbysatish.blogspot.com/2010/08/sql-server-replace-multiple-spaces-with.html

    再看一遍,似乎只是所选答案的版本略有不同。

    【讨论】:

    • 再看一遍,似乎只是所选答案的一个稍微不同的版本。 - 然后应该删除。我们不需要同一主题的一百种变体..
    【解决方案8】:

    这是我创建的一个简单函数,用于清除字符串之前或之后的任何空格以及字符串中的多个空格。它可以优雅地一次处理多达 108 个空格和字符串中的多个块。如果需要,您可以通过添加具有更大空间块的附加行来将其增加 8 倍。尽管它在大型应用程序中被普遍使用,但它似乎执行得很快并且没有引起任何问题。

    CREATE FUNCTION [dbo].[fnReplaceMultipleSpaces] (@StrVal AS VARCHAR(4000)) 
    RETURNS VARCHAR(4000) 
    AS 
    BEGIN
    
        SET @StrVal = Ltrim(@StrVal)
        SET @StrVal = Rtrim(@StrVal)
    
        SET @StrVal = REPLACE(@StrVal, '                ', ' ')  -- 16 spaces
        SET @StrVal = REPLACE(@StrVal, '        ', ' ')  -- 8 spaces
        SET @StrVal = REPLACE(@StrVal, '    ', ' ')  -- 4 spaces
        SET @StrVal = REPLACE(@StrVal, '  ', ' ')  -- 2 spaces
        SET @StrVal = REPLACE(@StrVal, '  ', ' ')  -- 2 spaces (for odd leftovers)
    
    RETURN @StrVal
    
    END
    

    【讨论】:

      【解决方案9】:

      可以通过函数递归完成:

      CREATE FUNCTION dbo.RemSpaceFromStr(@str VARCHAR(MAX)) RETURNS VARCHAR(MAX) AS
      BEGIN
        RETURN (CASE WHEN CHARINDEX('  ', @str) > 0 THEN
          dbo.RemSpaceFromStr(REPLACE(@str, '  ', ' ')) ELSE @str END);
      END
      

      那么,例如:

      SELECT dbo.RemSpaceFromStr('some   string    with         many     spaces') AS NewStr
      

      返回:

      NewStr
      some string with many spaces
      

      或基于@agdk26 或@Neil Knight 描述的方法的解决方案(但更安全)
      两个例子都返回上面的输出:

      SELECT REPLACE(REPLACE(REPLACE('some   string    with         many     spaces'
        , '  ', ' ' + CHAR(7)), CHAR(7) + ' ', ''), ' ' + CHAR(7), ' ') AS NewStr 
      --but it remove CHAR(7) (Bell) from string if exists...
      

      SELECT REPLACE(REPLACE(REPLACE('some   string    with         many     spaces'
        , '  ', ' ' + CHAR(7) + CHAR(7)), CHAR(7) + CHAR(7) + ' ', ''), ' ' + CHAR(7) + CHAR(7), ' ') AS NewStr
      --but it remove CHAR(7) + CHAR(7) from string
      

      它是如何工作的:

      注意:
      用于替换空格的字符/字符串不应存在于字符串的开头或结尾,并且是独立的。

      【讨论】:

      • 我有点喜欢递归函数的想法。有什么需要注意的吗?
      【解决方案10】:

      方法#1

      第一种方法是用不常见的符号组合替换单词之间的多余空格作为临时标记。然后您可以使用替换函数而不是循环替换临时标记符号。

      这是一个替换字符串变量中的文本的代码示例。

      DECLARE @testString AS VARCHAR(256) = ' Test        text   with  random*        spacing. Please normalize  this spacing!';
      SELECT REPLACE(REPLACE(REPLACE(@testString, ' ', '*^'), '^*', ''), '*^', ' ');
      

      执行时间测试#1:在此替换方法的十次运行中,服务器回复的平均等待时间为 1.7 毫秒,总执行时间为 4.6 毫秒。 执行时间测试 #2:服务器回复的平均等待时间为 1.7 毫秒,总执行时间为 3.7 毫秒。

      方法#2

      第二种方法不如第一种优雅,但也能完成工作。此方法通过嵌套四个(或更多)替换语句来工作,这些语句将两个空格替换为一个空格。

      DECLARE @testString AS VARCHAR(256) = ' Test        text   with  random*        spacing. Please normalize  this spacing!';
      SELECT REPLACE(REPLACE(REPLACE(REPLACE(@testString,' ',' '),' ',' '),' ',' '),' ',' ')
      

      执行时间测试 #1:在此替换方法的十次运行中,服务器回复的平均等待时间为 1.9 毫秒,总执行时间为 3.8 毫秒。 执行时间测试 #2:服务器回复的平均等待时间为 1.8 毫秒,总执行时间为 4.8 毫秒。

      方法#3

      替换单词之间多余空格的第三种方法是使用简单的循环。您可以在 while 循环中检查多余的空格,然后使用 replace 函数在循环的每次迭代中减少多余的空格。

      DECLARE @testString AS VARCHAR(256) = ' Test text with random* spacing. Please normalize this spacing!';
      WHILE CHARINDEX(' ',@testString) > 0
      SET @testString = REPLACE(@testString, ' ', ' ')
      SELECT @testString
      

      执行时间测试 #1:在此替换方法的十次运行中,服务器回复的平均等待时间为 1.8 毫秒,总执行时间为 3.4 毫秒。 执行时间测试 #2:服务器回复的平均等待时间为 1.9 毫秒,总执行时间为 2.8 毫秒。

      【讨论】:

      • 你的代码示例搞砸了
      【解决方案11】:

      你可以试试这个:

      select Regexp_Replace('single    spaces   only','( ){2,}', ' ') from dual;
      

      【讨论】:

      • DECLARE @str varchar(150) SET @str='Hello Welcome to World of .net' Select REPLACE(REPLACE(REPLACE(@str,' ','{}'),'}{ ',''),'{}',' ')
      • 人们在没有提供解释的情况下对该答案投了反对票。我相信这是因为 SQL Server 没有像 Oracle 那样的原生 Regexp_Replace() 函数。 (reference)如果您要投反对票,请解释原因,以便作者和未来的读者从中学习。
      【解决方案12】:

      我使用 FOR XML PATH 解决方案来replace multiple spaces into single space

      这个想法是用 XML 标记替换空格 然后将 XML 字符串拆分为没有 XML 标记的字符串片段 最后通过在两个字符串之间添加单个空格字符来连接这些字符串值

      这是如何调用最终的 UDF 函数

      select dbo.ReplaceMultipleSpaces('   Sample   text  with  multiple  space     ')
      

      【讨论】:

      • 这是一个仅链接的答案,如果链接的资源死亡,它将不再有用。请将链接的相关部分复制到您的答案中,请
      【解决方案13】:

      只是添加另一个方法-

      在 SQL Server 中用单个空格替换多个空格而不使用 REPLACE-

      DECLARE @TestTable AS TABLE(input VARCHAR(MAX));
      
      INSERT INTO @TestTable VALUES
      ('HAPPY         NEWYEAR     2020'),
      ('WELCOME       ALL     !');
      
      SELECT
          CAST('<r><![CDATA[' + input + ']]></r>' AS XML).value('(/r/text())[1] cast as xs:token?','VARCHAR(MAX)')
          AS Expected_Result
      FROM @TestTable;
      
      --OUTPUT
      /*
      Expected_Result
      HAPPY NEWYEAR 2020
      WELCOME ALL !
      */
      

      【讨论】:

        【解决方案14】:

        请在下面找到代码

        select trim(string_agg(value,' ')) from STRING_SPLIT('  single    spaces   only  ',' ')
        where value<>' '
        

        这对我有用.. 希望这会有所帮助...

        【讨论】:

        • 请注意,文档主动声明:输出行可能按任何顺序排列。顺序不能保证与输入字符串中子字符串的顺序相匹配 - STRING_SPLIT 通常会按输入中出现的顺序返回子字符串,但如果它确实以不同的顺序返回单词,此方法将有效地销毁输入字符串
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-05
        • 2013-12-02
        • 1970-01-01
        • 2015-03-27
        • 2013-07-03
        • 2016-06-16
        相关资源
        最近更新 更多