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

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

那么

'single    spaces   only'

需要被转变成

'single spaces only'

下面的方法不起作用

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

因为它会导致

'single  spaces  only'

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

有什么想法吗?

154452 次浏览

更整洁的是:

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

产出:

选择单个空格

这种方法可行:

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


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


select @test

这有点蛮力,但会有用的

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

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

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
update mytable
set myfield = replace (myfield, '  ',  ' ')
where charindex('  ', myfield) > 0

替换将工作在所有的双空格,无需放在多个替换。这是基于集合的解决方案。

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

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'

在寻找答案的过程中发现了这个:

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

在第二次看,似乎只是一个选定的答案略有不同的版本。

下面是我创建的一个简单函数,用于清除字符串之前或之后的所有空格以及字符串中的多个空格。它优雅地处理约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

它可以通过函数递归地完成:

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

工作原理: enter image description here

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

方法 # 1

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

下面是一个代码示例,它替换 String 变量中的文本。

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

执行时间测试 # 1: 在这个替换方法的10次运行中,服务器响应的平均等待时间为1.7毫秒,总执行时间为4.6毫秒。 执行时间测试 # 2: 服务器应答的平均等待时间为1.7毫秒,总执行时间为3.7毫秒。

方法二

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

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

执行时间测试 # 1: 在这个替换方法的10次运行中,服务器响应的平均等待时间为1.9毫秒,总执行时间为3.8毫秒。 执行时间测试 # 2: 服务器应答的平均等待时间为1.8毫秒,总执行时间为4.8毫秒。

方法 # 3

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

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: 在这个替换方法的10次运行中,服务器响应的平均等待时间为1.8毫秒,总执行时间为3.4毫秒。 执行时间测试 # 2: 服务器响应的平均等待时间为1.9毫秒,总执行时间为2.8毫秒。

你可以试试这个:

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

我对 将多个空格替换为单个空格使用 FORXMLPATH 解决方案

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

下面是如何调用 final UDF 函数

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

只是添加另一个方法-

使用 REPLACE 在 SQLServer-中用单个空间替换多个空间

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

请查找以下代码

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

这对我有用。 希望这个能帮上忙。

使用“最新的”SQLServer 版本(兼容级别130) ,您还可以使用 string_splitstring_agg

当提供第三个参数时,string _ split 可以返回序数列。(https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql?view=sql-server-ver16#enable_ordinal).所以我们可以保持 string_split的顺序。

使用公共表表达式:

with cte(value) as (select value from string_split('  a b   c d     e     ', ' ', 1) where value <> '' order by ordinal offset 0 rows)
select string_agg(value, ' ') from cte

a b c d e 的结果是 a b c d e