Sql server 将T-SQL中的重复空格替换为单个空格

Sql server 将T-SQL中的重复空格替换为单个空格,sql-server,tsql,Sql Server,Tsql,我需要确保给定字段的字符之间不存在超过一个空格(我不关心所有空格,只关心空格) 所以 需要变成 'single spaces only' 下面的方法不起作用 select replace('single spaces only',' ',' ') 因为这会导致 'single spaces only' 我更愿意坚持使用原生T-SQL,而不是基于CLR的解决方案 思想?更整洁: select string = replace(replace(replace(' select

我需要确保给定字段的字符之间不存在超过一个空格(我不关心所有空格,只关心空格)

所以

需要变成

'single spaces only'
下面的方法不起作用

select replace('single    spaces   only','  ',' ')
因为这会导致

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

思想?

更整洁:

select string = replace(replace(replace(' select   single       spaces',' ','<>'),'><',''),'<>',' ')
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
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.strip_spaces(myText) FROM myTable
替换将在所有双空格上工作,无需放入多个替换。这是基于集合的解决方案

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

试试这个..

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


在挖掘答案时发现:

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
完整答案(带解释)来自:


仔细看,这似乎只是所选答案的一个稍有不同的版本。

这里是我创建的一个简单函数,用于清理字符串前后的任何空格以及字符串中的多个空格。它在一次拉伸中优雅地处理多达108个空格和字符串中的块。您可以将其增加f如果需要的话,通过添加额外的行和更大的空格块来实现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 strip_spaces(@str varchar(8000))
RETURNS varchar(8000) AS
BEGIN 
    WHILE CHARINDEX('  ', @str) > 0 
        SET @str = REPLACE(@str, '  ', ' ')

    RETURN @str
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...

工作原理:

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

方法#1

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

下面是一个代码示例,用于替换字符串变量中的文本

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

第二种方法不像第一种方法那么优雅,但也能完成任务。这种方法通过嵌套四个(或更多)replace语句,用一个空格替换两个空格

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

您可以尝试以下方法:

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

我使用XML路径解决方案

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

下面是如何调用最终的UDF函数

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

我通常使用这种方法:

declare @s varchar(50)
set @s = 'TEST         TEST'
select REPLACE(REPLACE(REPLACE(@s,' ','[o][c]'),'[c][o]',''),'[o][c]',' ')
只是添加了另一种方法-

使用单个空间替换多个空间而不使用SQL Server中的替换-

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 !
*/
将@TestTable声明为表(输入VARCHAR(MAX));
插入到@TestTable值中
(“2020年新年快乐”),
(‘欢迎大家!);
挑选
强制转换(“”为XML).value('(/r/text())[1]强制转换为xs:token?','VARCHAR(MAX)'
果然
来自@TestTable;
--输出
/*
预期结果
2020年新年快乐
欢迎大家!
*/

请查找下面的代码

select trim(string_agg(value,' ')) from STRING_SPLIT('  single    spaces   only  ',' ')
where value<>' '
从string_SPLIT('single spaces only','')中选择trim(string_agg(value,''))
其中值为“”
这对我很有用。。
希望这有帮助…

你可以用REGEX replace来做这件事。如果你想删除字符串前后的空格,那么可以用LTRIM,RTRIM来包装这个替换。只要你的字符串不包含太多的<或>符号。对我来说似乎很脆弱。真正优雅的hack。升级。任何两个如果输入文本中可能存在字符,则可以使用racter作为中间部分。Chris,可以使用不可打印的ASCII字符,如CHAR(17)和CHAR(18),因为这些将永远不会出现在您的输入文本中。比接受答案的循环速度还要快。我必须仔细研究一下,才能发现您使用的是相同的代码,但您在文章中击败了我,所以向上投票。多个REPLACE()调用是不礼貌的,但是如果预期的“额外”数量空间是可预测的,而且相对较小,它可以很好地满足OP的要求,即不通过CLR.Wrapping in函数和cha调用正则表达式代码
declare @s varchar(50)
set @s = 'TEST         TEST'
select REPLACE(REPLACE(REPLACE(@s,' ','[o][c]'),'[c][o]',''),'[o][c]',' ')
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<>' '