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?


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


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

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

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.


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.


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

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


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.


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'

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     ')

0
 DECLARE @str varchar(150)
SET @str='Hello    My   name  is Jiyaul   mustafa'
Select REPLACE(REPLACE(REPLACE(@str,' ','{}'),'}{',''),'{}',' ')

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]',' ')

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

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


-1

Sie können dies versuchen:

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

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


Ich habe diese Lösung in meinen Fragen als nicht den Bedarf erfüllend bezeichnet, aber danke.
Christoph
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.