Sostituisci gli spazi duplicati con un singolo spazio in T-SQL


100

Devo assicurarmi che un determinato campo non abbia più di uno spazio (non sono preoccupato per tutto lo spazio bianco, solo spazio) tra i caratteri.

Così

'single    spaces   only'

deve essere trasformato in

'single spaces only'

Quanto segue non funzionerà

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

come risulterebbe

'single  spaces  only'

Preferirei davvero restare con T-SQL nativo piuttosto che con una soluzione basata su CLR.

Pensieri?


Puoi farlo con una sostituzione REGEX
Raj More

Risposte:


326

Ancora più ordinato:

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

Produzione:

selezionare singoli spazi


6
Se vuoi rimuovere gli spazi all'inizio e alla fine della stringa, avvolgi la sostituzione in un LTRIM, RTRIM e lo farà per te.
Neil Knight

5
Finché la tua stringa non contiene molti segni <o>. Sembra fragile per i miei gusti.
JohnFx

8
Trucco davvero elegante. Votato. È possibile utilizzare due caratteri qualsiasi per la parte centrale se <> sono potenzialmente nel testo di input.
richardtallent

32
Chris, puoi usare caratteri ASCII non stampabili come CHAR (17) e CHAR (18), poiché questi non saranno MAI nel testo di input. Ancora più veloce del ciclo della risposta accettata.
richardtallent

7
Ho dovuto guardare davvero questo per un momento per capire che hai usato '> <', '' Nessuno spazio per sostituire ma ora che ho capito ... è molto brillante. Mi è piaciuto molto il suggerimento di @richardtallent di utilizzare i caratteri ASCII non stampabili la cui combinazione aggiunta produce: REPLACE (REPLACE (REPLACE (LastName, '', 'CHAR (17) CHAR (18)'), 'CHAR (18 ) CHAR (17) ',' '),' CHAR (17) CHAR (18) ',' ')
Anthony Griggs

25

Questo funzionerebbe:

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

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

select @test

1
Avvolgere la funzione e cambiare varchar (100) in nvarchar (max)
Christoph

La differenza tra gli script di James e Neil è che James viene eseguito anche se il ciclo mentre, per esperienza personale, averlo eseguito anche se 50.000 record di una tabella tende ad essere molto lento, quindi è necessario crearlo come procedura e passare un record e alcuni lavori potresti non avere il permesso di creare una nuova procedura di band. Usi di Neil per-esistente funzioni perché utilizza <>, se si dispone di una stringa come "release < now"allora si otterrà "release<><><<><>now", "release<<>now", "release< now", la sua lo stesso con una qualsiasi coppia di simboli, se si dispone di uno solo della coppia, allora sta andando a muoversi
Memor-X

1
eseguire questo attraverso 50k record dovrebbe essere velocissimo, esaminerei altri problemi se questo è il tuo problema.
user3486773

17

Se sai che non ci sarà più di un certo numero di spazi di fila, potresti semplicemente annidare la sostituzione:

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

4 sostituzioni dovrebbero risolvere fino a 16 spazi consecutivi (16, poi 8, poi 4, poi 2, poi 1)

Se potesse essere significativamente più lungo, allora dovresti fare qualcosa come una funzione in linea:

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

    RETURN @str
END

Allora fallo e basta

SELECT dbo.strip_spaces(myText) FROM myTable

Brad, avevo un codice quasi identico ma mi hai battuto al Post, quindi vota positivamente. Più chiamate REPLACE () sono hacker, ma se il numero di spazi "extra" previsti è prevedibile e relativamente piccolo, andrà benissimo e soddisferà il requisito dell'OP di non chiamare il codice RegEx tramite il CLR.
richardtallent

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

La sostituzione funzionerà su tutti i doppi spazi, non è necessario inserire più sostituzioni. Questa è la soluzione basata su set.


Questo non comprimerebbe 4 spazi in 2?
Christoph

Ho chiamato questa soluzione nelle mie domande perché non soddisfa la necessità, ma grazie.
Christoph

6

Può essere fatto ricorsivamente tramite la funzione:

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

quindi, ad esempio:

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

ritorna:

NewStr
some string with many spaces

Oppure la soluzione basata sul metodo descritto da @ agdk26 o @Neil Knight (ma più sicuro)
entrambi gli esempi restituiscono l'output sopra:

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...

o

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

Come funziona: inserisci qui la descrizione dell'immagine

Attenzione: il carattere
/ la stringa utilizzati per sostituire gli spazi non dovrebbero esistere all'inizio o alla fine della stringa e stare da soli.


1
Mi piace l'idea di una funzione ricorsiva per questo. c'è qualcosa di cui essere a conoscenza?
Zach Smith il

5

Questa è una forza piuttosto bruta, ma funzionerà

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

Ecco una semplice funzione che ho creato per pulire eventuali spazi prima o dopo e più spazi all'interno di una stringa. Gestisce con grazia fino a circa 108 spazi in un unico tratto e tanti blocchi quanti sono nella stringa. Puoi aumentarlo di fattori di 8 aggiungendo righe aggiuntive con blocchi di spazi più grandi, se necessario. Sembra funzionare rapidamente e non ha causato problemi nonostante il suo uso generalizzato in una grande applicazione.

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

Metodo n. 1

Il primo metodo consiste nel sostituire gli spazi aggiuntivi tra le parole con una combinazione di simboli insolita come indicatore temporaneo. Quindi è possibile sostituire i simboli marker temporanei utilizzando la funzione di sostituzione anziché un ciclo.

Ecco un esempio di codice che sostituisce il testo all'interno di una variabile String.

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

Test del tempo di esecuzione n. 1: in dieci esecuzioni di questo metodo di sostituzione, il tempo di attesa medio per le risposte del server è stato di 1,7 millisecondi e il tempo di esecuzione totale è stato di 4,6 millisecondi. Test del tempo di esecuzione n. 2: il tempo di attesa medio sulle risposte del server è stato di 1,7 millisecondi e il tempo di esecuzione totale è stato di 3,7 millisecondi.

Metodo n. 2

Il secondo metodo non è così elegante come il primo, ma fa anche il suo lavoro. Questo metodo funziona annidando quattro (o facoltativamente più) istruzioni di sostituzione che sostituiscono due spazi vuoti con uno spazio vuoto.

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

Test del tempo di esecuzione n. 1: in dieci esecuzioni di questo metodo di sostituzione, il tempo di attesa medio per le risposte del server è stato di 1,9 millisecondi e il tempo di esecuzione totale è stato di 3,8 millisecondi. Test del tempo di esecuzione n. 2: il tempo di attesa medio sulle risposte del server è stato di 1,8 millisecondi e il tempo di esecuzione totale è stato di 4,8 millisecondi.

Metodo n. 3

Il terzo metodo per sostituire gli spazi extra tra le parole consiste nell'utilizzare un semplice ciclo. Puoi controllare gli spazi extra in un ciclo while e quindi utilizzare la funzione di sostituzione per ridurre gli spazi extra con ogni iterazione del ciclo.

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

Test del tempo di esecuzione n. 1: in dieci esecuzioni di questo metodo di sostituzione, il tempo di attesa medio per le risposte del server è stato di 1,8 millisecondi e il tempo di esecuzione totale è stato di 3,4 millisecondi. Test del tempo di esecuzione n. 2: il tempo di attesa medio per le risposte del server è stato di 1,9 millisecondi e il tempo di esecuzione totale è stato di 2,8 millisecondi.


1

Questa è la soluzione tramite sostituzione multipla, che funziona per qualsiasi stringa (non necessita di caratteri speciali, che non fanno parte della stringa).

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'

bella cosa, ma cambiare "abe" in "ax"
Adam Silenko

0

Uso la soluzione FOR XML PATH per sostituire più spazi in un unico spazio

L'ideaèdi sostituire gli spazi con tag XML Quindi dividere la stringa XML in frammenti di stringa senza tag XML Infine concatenare quei valori di stringa aggiungendo singoli caratteri di spazio tra due

Ecco come può essere chiamata la funzione UDF finale

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

In genere utilizzo questo approccio:

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

0

Basta aggiungere un altro metodo-

Sostituzione di più spazi con uno spazio singolo SENZA utilizzare REPLACE in 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 !
*/

0

Si prega di trovare sotto il codice

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

Questo ha funzionato per me .. Spero che questo aiuti ...


-1

Puoi provare questo:

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

DECLARE @str varchar (150) SET @ str = 'Hello Welcome to World of .net' Seleziona REPLACE (REPLACE (REPLACE (@str, '', '{}'), '} {', ''), '{ } ',' ')
Codice

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

Prova questo..


Ho chiamato questa soluzione nelle mie domande perché non soddisfa la necessità, ma grazie.
Christoph
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.