Ersetzen Sie doppelte Leerzeichen durch ein einzelnes Leerzeichen in T-SQL

100

Ich muss sicherstellen, dass ein bestimmtes Feld nicht mehr als ein Leerzeichen (ich mache mir keine Gedanken über alle Leerzeichen, nur Leerzeichen) zwischen Zeichen hat.

So

'single    spaces   only'

muss in verwandelt werden

'single spaces only'

Das Folgende wird nicht funktionieren

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

wie es dazu führen würde

'single  spaces  only'

Ich würde wirklich lieber bei nativem T-SQL bleiben als bei einer CLR-basierten Lösung.

Gedanken?

Christoph
quelle
Sie können dies mit einem REGEX-Ersatz tun
Raj More

Antworten:

325

Noch aufgeräumter:

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

Ausgabe:

Wählen Sie einzelne Leerzeichen aus

Neil Knight
quelle
6
Wenn Sie die Leerzeichen am vorderen und Ende der Zeichenfolge entfernen möchten, wickeln Sie das Ersetzen in ein LTRIM, RTRIM, und es wird dies für Sie tun.
Neil Knight
5
Solange Ihre Zeichenfolge nicht viele <oder> Zeichen enthält. Scheint für meinen Geschmack zerbrechlich.
JohnFx
8
Wirklich eleganter Hack. Upvoted. Für den mittleren Teil können zwei beliebige Zeichen verwendet werden, wenn <> möglicherweise im Eingabetext enthalten sind.
richardtallent
32
Chris, du kannst nicht druckbare ASCII-Zeichen wie CHAR (17) und CHAR (18) verwenden, da diese NIEMALS in deinem Eingabetext enthalten sein werden. Immer noch schneller als das Schleifen der akzeptierten Antwort.
richardtallent
7
Ich musste mir das einen Moment lang ansehen, um herauszufinden, dass Sie das '> <', '' Kein Platz ersetzen, aber jetzt, wo ich es bekomme ... es ist sehr brillant. Ich mochte den @richardtallent-Vorschlag, die nicht druckbaren ASCII-Zeichen zu verwenden, deren zusätzliche Kombination Folgendes ergibt: REPLACE (REPLACE (REPLACE (Nachname, '', 'CHAR (17) CHAR (18)'), 'CHAR (18) ) CHAR (17) ',' '),' CHAR (17) CHAR (18) ',' ')
Anthony Griggs
25

Das würde funktionieren:

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

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

select @test
James Wiseman
quelle
1
Umhüllung der Funktion und Änderung von varchar (100) in nvarchar (max)
Christoph
Der Unterschied zwischen James 'und Neils Skripten besteht darin, dass James während einer Schleife ausgeführt wird, die nach persönlicher Erfahrung in der Regel sehr langsam ausgeführt wird, wenn 50.000 Datensätze einer Tabelle ausgeführt werden. Sie müssen sie daher als Prozedur erstellen und einen Datensatz und einige übergeben Jobs, für die Sie möglicherweise keine Berechtigung zum Erstellen einer neuen Prozedur haben. Neils Anwendungen pro vorhandenen Funktionen , weil es verwendet <>, wenn Sie eine Zeichenfolge haben wie "release < now"dann werden Sie erhalten "release<><><<><>now", "release<<>now", "release< now", es ist das gleiche mit jedem Paar von Symbolen, wenn Sie eine einzelne von dem Paar haben , dann es geht zu bewegen
Memor-X
1
Das Durchlaufen von 50.000 Datensätzen sollte schnell gehen. Ich würde mich mit anderen Problemen befassen, wenn dies Ihr Problem ist.
user3486773
17

Wenn Sie wissen, dass nicht mehr als eine bestimmte Anzahl von Leerzeichen in einer Reihe vorhanden ist, können Sie das Ersetzen einfach verschachteln:

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

4 Ersetzungen sollten bis zu 16 aufeinanderfolgende Leerzeichen korrigieren (16, dann 8, dann 4, dann 2, dann 1).

Wenn es wesentlich länger dauern könnte, müssten Sie so etwas wie eine Inline-Funktion ausführen:

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

    RETURN @str
END

Dann mach es einfach

SELECT dbo.strip_spaces(myText) FROM myTable
BradC
quelle
Brad, ich hatte fast identischen Code, aber du hast mich auf die Post geschlagen, also stimme zu. Mehrere REPLACE () -Aufrufe sind hackisch, aber wenn die Anzahl der erwarteten "zusätzlichen" Leerzeichen vorhersehbar und relativ gering ist, reicht dies aus und erfüllt die Anforderung des OP, keinen RegEx-Code über die CLR aufzurufen.
richardtallent
6
update mytable
set myfield = replace (myfield, '  ',  ' ')
where charindex('  ', myfield) > 0 

Ersetzen funktioniert auf allen doppelten Leerzeichen, ohne dass mehrere Ersetzungen erforderlich sind. Dies ist die satzbasierte Lösung.

HLGEM
quelle
Würde dies nicht 4 Felder in 2 zusammenbrechen?
Christoph
Ich habe diese Lösung in meinen Fragen als nicht den Bedarf erfüllend bezeichnet, aber danke.
Christoph
6

Dies kann rekursiv über die Funktion erfolgen:

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

dann zum Beispiel:

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

kehrt zurück:

NewStr
some string with many spaces

Oder die Lösung, die auf der von @ agdk26 oder @Neil Knight (aber sicherer) beschriebenen Methode basiert.
Beide Beispiele geben die Ausgabe oben zurück:

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

oder

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

Wie es funktioniert: Geben Sie hier die Bildbeschreibung ein

Achtung:
Zeichen / Zeichenfolgen, die zum Ersetzen von Leerzeichen verwendet werden, sollten am Anfang oder Ende der Zeichenfolge nicht vorhanden sein und eigenständig sein.

Adam Silenko
quelle
1
Ich mag die Idee einer rekursiven Funktion dafür. Gibt es etwas zu beachten?
Zach Smith
5

Dies ist etwas brutale Gewalt, wird aber funktionieren

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
quelle
2

Hier ist eine einfache Funktion, die ich zum Bereinigen von Leerzeichen vor oder nach und mehrerer Leerzeichen innerhalb einer Zeichenfolge erstellt habe. Es verarbeitet bis zu 108 Leerzeichen in einer einzigen Strecke und so viele Blöcke, wie in der Zeichenfolge vorhanden sind. Sie können dies um den Faktor 8 erhöhen, indem Sie bei Bedarf zusätzliche Zeilen mit größeren Leerzeichen hinzufügen. Es scheint schnell zu funktionieren und hat trotz seiner allgemeinen Verwendung in einer großen Anwendung keine Probleme verursacht.

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
Robert Petolillo
quelle
1

Fand dies beim Graben nach einer Antwort:

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

Die vollständige Antwort (mit Erklärung) wurde abgerufen von: http://techtipsbysatish.blogspot.com/2010/08/sql-server-replace-multiple-spaces-with.html

Auf den zweiten Blick scheint es sich nur um eine etwas andere Version der ausgewählten Antwort zu handeln.

Limey
quelle
1

Methode 1

Die erste Methode besteht darin, zusätzliche Leerzeichen zwischen Wörtern durch eine ungewöhnliche Symbolkombination als temporären Marker zu ersetzen. Anschließend können Sie die temporären Markierungssymbole mithilfe der Ersetzungsfunktion anstelle einer Schleife ersetzen.

Hier ist ein Codebeispiel, das Text innerhalb einer String-Variablen ersetzt.

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

Ausführungszeittest Nr. 1: In zehn Durchläufen dieser Ersetzungsmethode betrug die durchschnittliche Wartezeit bei Serverantworten 1,7 Millisekunden und die Gesamtausführungszeit 4,6 Millisekunden. Ausführungszeittest Nr. 2: Die durchschnittliche Wartezeit bei Serverantworten betrug 1,7 Millisekunden und die Gesamtausführungszeit 3,7 Millisekunden.

Methode 2

Die zweite Methode ist nicht ganz so elegant wie die erste, erledigt aber auch die Arbeit. Diese Methode verschachtelt vier (oder optional mehrere) Ersetzungsanweisungen, die zwei Leerzeichen durch ein Leerzeichen ersetzen.

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

Ausführungszeittest Nr. 1: In zehn Durchläufen dieser Ersetzungsmethode betrug die durchschnittliche Wartezeit bei Serverantworten 1,9 Millisekunden und die Gesamtausführungszeit 3,8 Millisekunden. Ausführungszeittest Nr. 2: Die durchschnittliche Wartezeit bei Serverantworten betrug 1,8 Millisekunden und die Gesamtausführungszeit 4,8 Millisekunden.

Methode 3

Die dritte Methode zum Ersetzen zusätzlicher Leerzeichen zwischen Wörtern besteht in der Verwendung einer einfachen Schleife. Sie können zusätzliche Leerzeichen in einer while-Schleife überprüfen und dann die Ersetzungsfunktion verwenden, um die zusätzlichen Leerzeichen bei jeder Iteration der Schleife zu reduzieren.

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

Ausführungszeittest Nr. 1: In zehn Durchläufen dieser Ersetzungsmethode betrug die durchschnittliche Wartezeit bei Serverantworten 1,8 Millisekunden und die Gesamtausführungszeit 3,4 Millisekunden. Ausführungszeittest Nr. 2: Die durchschnittliche Wartezeit bei Serverantworten betrug 1,9 Millisekunden und die Gesamtausführungszeit betrug 2,8 Millisekunden.


quelle
1

Dies ist die Lösung über mehrere Ersetzungen, die für alle Zeichenfolgen funktioniert (benötigt keine Sonderzeichen, die nicht Teil der Zeichenfolge sind).

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'
agdk26
quelle
schöne Sache, aber 'abe' in 'ax'
ändern
0

Ich verwende die FOR XML PATH-Lösung, um mehrere Leerzeichen in ein einzelnes Leerzeichen zu ersetzen

Die Idee ist, Leerzeichen durch XML-Tags zu ersetzen. Anschließend die XML-Zeichenfolge in Zeichenfolgenfragmente ohne XML-Tags aufteilen. Schließlich werden diese Zeichenfolgenwerte durch Hinzufügen einzelner Leerzeichen zwischen zwei verkettet

So kann die endgültige UDF-Funktion aufgerufen werden

select dbo.ReplaceMultipleSpaces('   Sample   text  with  multiple  space     ')
Eralper
quelle
0
 DECLARE @str varchar(150)
SET @str='Hello    My   name  is Jiyaul   mustafa'
Select REPLACE(REPLACE(REPLACE(@str,' ','{}'),'}{',''),'{}',' ')
JIYAUL MUSTAPHA
quelle
0

Ich benutze normalerweise diesen Ansatz:

declare @s varchar(50)
set @s = 'TEST         TEST'
select REPLACE(REPLACE(REPLACE(@s,' ','[o][c]'),'[c][o]',''),'[o][c]',' ')
Matthys Du Toit
quelle
0

Einfach eine andere Methode hinzufügen-

Ersetzen mehrerer Leerzeichen durch ein einzelnes Leerzeichen OHNE 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 !
*/
Arulmouzhi
quelle
0

Bitte finden Sie unten Code

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

Das hat bei mir funktioniert .. Hoffe das hilft ...

Lekhnath Pandey
quelle
-1

Sie können dies versuchen:

select Regexp_Replace('single    spaces   only','( ){2,}', ' ') from dual;
karthika harisankar
quelle
DECLARE @str varchar (150) SET @ str = 'Hallo, willkommen in World of .net' Wählen Sie REPLACE (REPLACE (REPLACE (@str, '', '{}'), '} {', ''), '{ } ',' ')
JIYAUL MUSTAPHA
-3
update mytable
set myfield = replace(myfield, '  ',  ' ')
where myfield like '%  %'

Versuche dies..

Henry
quelle
Ich habe diese Lösung in meinen Fragen als nicht den Bedarf erfüllend bezeichnet, aber danke.
Christoph