views:

166

answers:

5

I need to ensure that a given field does not have more than one space (not concerned about all white space, just space) between characters.

So

'single    spaces   only'

Needs to turn into

'single spaces only'

The below will not work

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

as it would result in

'single  spaces  only'

I would really prefer to stick with native TSQL rather than a CLR based solution.

Thoughts?

+6  A: 

Even tidier:

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

Output: select single spaces

Ardman
If you want to remove the spaces at the front and end of the string, then wrap the replace in an LTRIM, RTRIM and it will do it for you.
Ardman
As long as your string doesn't contain a lot of < or > signs. Seems to fragile for my liking.
JohnFx
Truly elegant hack. Upvoted. Any two characters could be used for the middle portion if <> are potentially in the input text.
richardtallent
That's pretty clever. I'd feel better with a less common character, but this is a cool idea.
BradC
Like it, but don't think we can safely reserve any characters. We don't have control over the input.
Christopherous 5000
Chris, you can use non-printable ASCII characters like as CHAR(17) and CHAR(18), as these will NEVER be in your input text. Still faster than the looping of the accepted answer.
richardtallent
+3  A: 

This would work:

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

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

select @test
James Wiseman
Wrapping in function and changing varchar(100) to nvarchar(max)
Christopherous 5000
A: 

see the answers to a similar/identical question: sql-method-to-replace-repeating-blanks-with-single-blanks

SAMills
looking for TSQL solution, but thanks
Christopherous 5000
A: 

This is somewhat brute force, but will work

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
JohnFx
+1  A: 

If you know there won't be more than a certain number of spaces in a row, you could just nest the replace:

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

4 replaces should fix up to 16 consecutive spaces (16, then 8, then 4, then 2, then 1)

If it could be significantly longer, then you'd have to do something like an in-line function:

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

    RETURN @str
END

Then just do

SELECT dbo.strip_spaces(myText) FROM myTable
BradC
Brad, I had almost identical code but you beat me to the Post, so upvote. Multiple REPLACE() calls are hackish, but if the number of expected "extra" spaces is predictable and relatively small, it'll do just fine and meet the OP's requirement not to call RegEx code via the CLR.
richardtallent
Best answer for us, but James Wiseman posted the essence of it first (granted not wrapped in a nice function)
Christopherous 5000