在T-SQL中用单个空格替换重复的空格


100

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

所以

'single    spaces   only'

需要变成

'single spaces only'

下面的行不通

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

因为这会导致

'single  spaces  only'

我真的更喜欢使用本地T-SQL,而不是基于CLR的解决方案。

有什么想法吗?


您可以使用REGEX替换来做到这一点
Raj More 2010年

Answers:


325

更整洁:

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

输出:

选择单个空格


6
如果要删除字符串开头和结尾的空格,则将替换内容包装在LTRIM,RTRIM中,它将为您完成。
尼尔·奈特

5
只要您的字符串不包含很多<或>符号。按照我的喜好似乎很脆弱。
JohnFx 2010年

8
真正优雅的hack。已投票。如果输入文本中可能包含<>,则任何两个字符都可以用作中间部分。
richardtallent

32
克里斯,您可以使用不可打印的ASCII字符,例如CHAR(17)和CHAR(18),因为这些字符永远不会出现在您的输入文本中。仍然比循环接受的答案更快。
richardtallent

7
我不得不花一点时间来弄清楚你使用的是'> <',''没有空格替换,但是现在我明白了...这非常出色。我非常喜欢@richardtallent的建议,建议使用不可打印的ASCII字符,将其添加的组合产生:REPLACE(REPLACE(REPLACE(LastName,'','CHAR(17)CHAR(18)'),'CHAR(18) )CHAR(17)',''),'CHAR(17)CHAR(18)','')
Anthony Griggs 2015年

25

这将工作:

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

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

select @test

1
包装功能并将varchar(100)更改为nvarchar(max)
Christoph

James和Neil的脚本之间的区别在于,James虽然运行while循环,但就个人经验而言,尽管在一个表的50,000条记录中运行它会非常缓慢,所以您需要将其创建为一个过程并传递一条记录和一些您可能没有创建新程序的权限。尼尔的用途每现有的功能,因为它使用<>,如果你有一个字符串像"release < now",那么你会得到"release<><><<><>now""release<<>now""release< now",它与任何对符号的相同,如果你有一对单一个接着它会移到
Memor-X

1
通过50k条记录运行它应该很快就能实现,如果这是您的问题,我会调查其他问题。
user3486773

17

如果您知道一行中最多只能有一定数量的空格,则可以嵌套替换:

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代码的要求。
richardtallent

6
update mytable
set myfield = replace (myfield, '  ',  ' ')
where charindex('  ', myfield) > 0 

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


这不会将4个空格折叠成2个吗?
Christoph

我在提出问题时称此解决方案不符合需求,但非常感谢。
Christoph

6

可以通过以下函数递归完成:

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

这个怎么运作: 在此处输入图片说明

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


1
我有点喜欢为此使用递归函数的想法。有什么要注意的吗?
扎克史密斯

5

这有点蛮力,但是可以用

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

2

这是我创建的一个简单函数,用于清除字符串前后的任何空格以及字符串中的多个空格。它可以一次处理多达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


1

方法1

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

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

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毫秒。


1

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

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”
Adam Silenko '16

0

我使用FOR XML PATH解决方案将多个空间替换为单个空间

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

这是最终UDF函数的调用方式

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

0
 DECLARE @str varchar(150)
SET @str='Hello    My   name  is Jiyaul   mustafa'
Select REPLACE(REPLACE(REPLACE(@str,' ','{}'),'}{',''),'{}',' ')

0

我通常使用这种方法:

declare @s varchar(50)
set @s = 'TEST         TEST'
select REPLACE(REPLACE(REPLACE(@s,' ','[o][c]'),'[c][o]',''),'[o][c]',' ')

0

只需添加另一种方法-

在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 !
*/


-1

您可以尝试以下方法:

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

DECLARE @str varchar(150)SET @ str ='你好,欢迎来到.net的世界'选择REPLACE(REPLACE(REPLACE(@str,'','{}'),'} {',''),'{ }','')
代码

-3
update mytable
set myfield = replace(myfield, '  ',  ' ')
where myfield like '%  %'

试试这个..


我在提出问题时称此解决方案不符合需求,但非常感谢。
Christoph
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.