Ersetzen Sie eine neue Zeile in TSQL

414

Ich möchte ein Zeilenumbruchzeichen in einer TSQL-Zeichenfolge ersetzen (oder entfernen). Irgendwelche Ideen?

Das Offensichtliche

REPLACE(@string, CHAR(13), '')

werde es einfach nicht tun ...

Peter
quelle

Antworten:

841

Tatsächlich kann eine neue Zeile in einem SQL-Befehl oder einer Skriptzeichenfolge CR, LF oder CR + LF sein. Um sie alle zu bekommen, brauchen Sie so etwas:

SELECT REPLACE(REPLACE(@str, CHAR(13), ''), CHAR(10), '')
RBarryYoung
quelle
5
@NielsBrinch Das wird gut funktionieren, solange dies die einzige Art von Zeilenumbruch in Ihren Zeichenfolgen ist. SQL Server unterstützt jedoch alle drei Typen. Wenn Sie jemals alle gespeicherten Systemprozeduren und Skriptansichten extrahiert haben, können Sie Instanzen aller drei finden, die von Microsoft selbst verwendet werden.
RBarryYoung
Dies funktionierte bei mir b / c, bevor ich diese Änderungskopie machte und beim Einfügen der Spaltendaten der Cursor am Ende des Textes mit zwei Leerzeichen angezeigt wurde. Nachdem Sie diese Änderung beim Kopieren und Einfügen in den Editor vorgenommen hatten, befand sich der Cursor direkt am Ende des Textes. Es verursachte ein Problem für mich b / c in unserer Front-End-GUI, das neue Zeilenzeichen wurde angezeigt.
Natur3
8
Wenn der Spaltendatentyp Text ist, müssen Sie zuerst in nvarchar umwandeln und dann SELECT REPLACE (REPLACE (cast (@str als nvarchar (max)), CHAR (13), ''), CHAR (10), '') ersetzen.
Akd
1
@ Slint Ja, guter Punkt. Um dies aus dem Client-Code zu verwenden, sollten Sie praktisch einen Spaltennamen hinzufügen. Obwohl es wahr ist, dass Sie oft davonkommen können, .columns[0]stattdessen zu verwenden.
RBarryYoung
2
Für die von mir verwendete Oracle-Version lautet die Anweisung CHR, nicht CHAR. Nur für den Fall, dass jemand versucht, über Oracle zu debuggen. Ansonsten gilt alles andere.
Sedona
143
REPLACE(@string, CHAR(13) + CHAR(10), '')
Mitch Wheat
quelle
2
Dies war die Methode, die ich zuerst ausprobiert habe, aber sie funktionierte nicht für alle Daten zuverlässig. @RBarryYoung hat es direkt oben.
Mark W Dickson
1
danke, ich musste dies ein wenig ändern, um für mich zu arbeiten, in meinem Fall ist es: replace (REPLACE (@string, CHAR (13), ''), CHAR (10), '')
user734028
36

Ich bin vielleicht ein Jahr zu spät zur Party, aber ich arbeite jeden Tag an Abfragen und MS-SQL und habe die integrierten Funktionen LTRIM () und RTRIM () satt (und muss sie immer zusammen aufrufen) Ich entschied, dass es höchste Zeit war, eine bessere TRIM-Funktion zu implementieren, um keine "schmutzigen" Daten abzufangen, die am Ende Zeilenumbrüche hatten. Ich würde Peer-Feedback begrüßen!

Haftungsausschluss : Dadurch werden tatsächlich erweiterte Leerzeichen (Tabulator, Zeilenvorschub, Wagenrücklauf usw.) entfernt (durch ein einzelnes Leerzeichen ersetzt) ​​und aus meiner ursprünglichen Antwort in "CleanAndTrim" umbenannt. Die Idee dabei ist , dass die Zeichenfolge nicht nicht brauchen solche zusätzlichen Sonder Leerzeichen im Inneren, und so , wenn sie am Kopf / Schwanz nicht auftreten, sollten sie mit einem einfachen Raum ersetzt werden. Wenn Sie solche Zeichen absichtlich in Ihrer Zeichenfolge gespeichert haben (z. B. in Ihrer Datenspalte, in der Sie dies ausführen möchten), TUN SIE ES NICHT! Verbessern Sie diese Funktion oder schreiben Sie eine eigene, die diese Zeichen buchstäblich nur von den Endpunkten der Zeichenfolge entfernt, nicht vom 'Körper'.

Okay, jetzt, da der Haftungsausschluss aktualisiert wurde, ist hier der Code.

-- =============================================
-- Description: TRIMs a string 'for real' - removes standard whitespace from ends,
-- and replaces ASCII-char's 9-13, which are tab, line-feed, vert tab,
-- form-feed, & carriage-return (respectively), with a whitespace
-- (and then trims that off if it's still at the beginning or end, of course).
-- =============================================
CREATE FUNCTION [fn_CleanAndTrim] (
       @Str nvarchar(max)
)
RETURNS nvarchar(max) AS
BEGIN
       DECLARE @Result nvarchar(max)

       SET @Result = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
              LTRIM(RTRIM(@Str)), CHAR(9), ' '), CHAR(10), ' '), CHAR(11), ' '), CHAR(12), ' '), CHAR(13), ' ')))

       RETURN @Result
END

Prost!

Ein weiterer Haftungsausschluss : Ihr typischer Windows-Zeilenumbruch ist CR + LF. Wenn Ihre Zeichenfolge diese enthält, werden Sie sie am Ende durch "doppelte" Leerzeichen ersetzen.

UPDATE, 2016 : Eine neue Version, mit der Sie diese Leerzeichen durch andere Zeichen Ihrer Wahlersetzen können! Dies umfasst auch Kommentare und die Umgehung der Windows CR + LF-Kopplung, dh das Ersetzen dieses bestimmten Zeichenpaars durch eine einzelne Ersetzung.

IF OBJECT_ID('dbo.fn_CleanAndTrim') IS NULL
    EXEC ('CREATE FUNCTION dbo.fn_CleanAndTrim () RETURNS INT AS BEGIN RETURN 0 END')
GO
-- =============================================
-- Author: Nate Johnson
-- Source: http://stackoverflow.com/posts/24068265
-- Description: TRIMs a string 'for real' - removes standard whitespace from ends,
-- and replaces ASCII-char's 9-13, which are tab, line-feed, vert tab, form-feed,
-- & carriage-return (respectively), with a whitespace or specified character(s).
-- Option "@PurgeReplaceCharsAtEnds" determines whether or not to remove extra head/tail
-- replacement-chars from the string after doing the initial replacements.
-- This is only truly useful if you're replacing the special-chars with something
-- **OTHER** than a space, because plain LTRIM/RTRIM will have already removed those.
-- =============================================
ALTER FUNCTION dbo.[fn_CleanAndTrim] (
    @Str NVARCHAR(MAX)
    , @ReplaceTabWith NVARCHAR(5) = ' '
    , @ReplaceNewlineWith NVARCHAR(5) = ' '
    , @PurgeReplaceCharsAtEnds BIT = 1
)
RETURNS NVARCHAR(MAX) AS
BEGIN
    DECLARE @Result NVARCHAR(MAX)

    --The main work (trim & initial replacements)
    SET @Result = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
        LTRIM(RTRIM(@Str))  --Basic trim
        , NCHAR(9), @ReplaceTabWith), NCHAR(11), @ReplaceTabWith)   --Replace tab & vertical-tab
        , (NCHAR(13) + NCHAR(10)), @ReplaceNewlineWith) --Replace "Windows" linebreak (CR+LF)
        , NCHAR(10), @ReplaceNewlineWith), NCHAR(12), @ReplaceNewlineWith), NCHAR(13), @ReplaceNewlineWith)))   --Replace other newlines

    --If asked to trim replacement-char's from the ends & they're not both whitespaces
    IF (@PurgeReplaceCharsAtEnds = 1 AND NOT (@ReplaceTabWith = N' ' AND @ReplaceNewlineWith = N' '))
    BEGIN
        --Purge from head of string (beginning)
        WHILE (LEFT(@Result, DATALENGTH(@ReplaceTabWith)/2) = @ReplaceTabWith)
            SET @Result = SUBSTRING(@Result, DATALENGTH(@ReplaceTabWith)/2 + 1, DATALENGTH(@Result)/2)

        WHILE (LEFT(@Result, DATALENGTH(@ReplaceNewlineWith)/2) = @ReplaceNewlineWith)
            SET @Result = SUBSTRING(@Result, DATALENGTH(@ReplaceNewlineWith)/2 + 1, DATALENGTH(@Result)/2)

        --Purge from tail of string (end)
        WHILE (RIGHT(@Result, DATALENGTH(@ReplaceTabWith)/2) = @ReplaceTabWith)
            SET @Result = SUBSTRING(@Result, 1, DATALENGTH(@Result)/2 - DATALENGTH(@ReplaceTabWith)/2)

        WHILE (RIGHT(@Result, DATALENGTH(@ReplaceNewlineWith)/2) = @ReplaceNewlineWith)
            SET @Result = SUBSTRING(@Result, 1, DATALENGTH(@Result)/2 - DATALENGTH(@ReplaceNewlineWith)/2)
    END

    RETURN @Result
END
GO
NateJ
quelle
Frühere Benutzer, bitte beachten Sie die Änderung und den Haftungsausschluss - und ich entschuldige mich für die anfänglichen Annahmen über Nutzung und Zweck.
NateJ
1
Neues Update! Testfälle finden Sie hier: sqlfiddle.com/#!6/585a2/1/0 - SQLFiddle schien bei meiner tatsächlichen Ausführung der Testfälle zu ersticken, daher habe ich stattdessen eine Tabelle "Testfallabfrage-Generator" erstellt & geben Sie die 9 Anweisungen zum Kopieren und Einfügen in Ihr eigenes SSMS-Fenster zum Ausführen (natürlich nach dem Erstellen des Schemas, dh der Funktion und der TestStrings-Tabelle).
NateJ
32

Die Newline in T-SQL wird durch CHAR (13) & CHAR (10) (Wagenrücklauf + Zeilenvorschub) dargestellt. Dementsprechend können Sie eine REPLACE-Anweisung mit dem Text erstellen, durch den Sie die neue Zeile ersetzen möchten.

REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')
Cerebrus
quelle
9
Dies ist nicht ganz das Gleiche wie die akzeptierte Antwort. Die akzeptierte Antwort entfernt jede Kombination von {13, 10}. Dadurch wird nur die spezifische Kombination von 13 bis 10 entfernt. Es macht keinen Unterschied für Windows-Zeilenenden, aber andere Codierungen werden hier übersehen.
Andrew Hill
24

Um das zu tun, was die meisten Leute wollen, erstellen Sie einen Platzhalter, der kein Zeilenumbruchzeichen ist. Dann können Sie tatsächlich die Ansätze kombinieren für:

REPLACE(REPLACE(REPLACE(MyField, CHAR(13) + CHAR(10), 'something else'), CHAR(13), 'something else'), CHAR(10), 'something else')

Auf diese Weise ersetzen Sie nur einmal. Der Ansatz von:

REPLACE(REPLACE(MyField, CHAR(13), ''), CHAR(10), '')

Funktioniert hervorragend, wenn Sie nur die CRLF-Zeichen entfernen möchten, aber wenn Sie einen Platzhalter wie
oder etwas anderes möchten , ist der erste Ansatz etwas genauer.

Schweinefleisch und Käse
quelle
6

Wenn Ihr Spaltendatentyp " Text " ist, erhalten Sie eine Fehlermeldung als

Meldung 8116, Ebene 16, Status 1, Zeile 2 Der Text des Argumentdatentyps ist für Argument 1 der Ersetzungsfunktion ungültig.

In diesem Fall müssen Sie den Text als nvarchar umwandeln und dann ersetzen

SELECT REPLACE(REPLACE(cast(@str as nvarchar(max)), CHAR(13), ''), CHAR(10), '')
akd
quelle
Ok, das sieht gut aus. Was ist, wenn das, was ich zu ersetzen versuche, "! Crlf" ist und ja, das ist ein Leerzeichen nach dem! Crlf. Die Sorge ist, dass dies in der Mitte des Strings auftritt. Könnte ich damit durchkommen: SELECT REPLACE (REPLACE (cast (@str als nvarchar (MAX)), CHAR (33), CHAR (13), CHAR (10), CHAR (32), '') oder habe ich dies falsch geschrieben? Die Zeichenfolge sieht folgendermaßen aus: Ermöglichen Sie Remoteangreifern, einen Sandbox-Schutzmechanismus zu umgehen und Berechtigungen über eine gestaltete Website zu erhalten, auf die mit Internet Explorer zugegriffen wird Wort t! hat ... das ist mein
Problempunkt
3

Wenn Sie ein Problem haben, bei dem Sie nur nachfolgende Zeichen entfernen möchten , können Sie Folgendes versuchen:

WHILE EXISTS
(SELECT * FROM @ReportSet WHERE
    ASCII(right(addr_3,1)) = 10
    OR ASCII(right(addr_3,1)) = 13
    OR ASCII(right(addr_3,1)) = 32)
BEGIN
    UPDATE @ReportSet
    SET addr_3 = LEFT(addr_3,LEN(addr_3)-1)
    WHERE 
    ASCII(right(addr_3,1)) = 10
    OR ASCII(right(addr_3,1)) = 13
    OR ASCII(right(addr_3,1)) = 32
END

Dies löste ein Problem mit Adressen, bei denen eine Prozedur ein Feld mit einer festen Anzahl von Zeilen erstellte, selbst wenn diese Zeilen leer waren. Um Platz in meinem SSRS-Bericht zu sparen, habe ich sie gekürzt.

DaveX
quelle
1

Wenn Sie eine offene Prozedur mit sp_helptext haben, kopieren Sie einfach den gesamten Text in eine neue SQL-Abfrage und drücken Sie Strg + H. Verwenden Sie den regulären Ausdruck, um ^ \ n in das Suchfeld zu ersetzen und durch Leerzeichen zu ersetzen. Weitere Details finden Sie im Bild. Geben Sie hier die Bildbeschreibung ein

Rohan
quelle
1

Zur @ Cerebrus-Lösung: Für H2 für Zeichenfolgen wird "+" nicht unterstützt. Damit:

REPLACE(string, CHAR(13) || CHAR(10), 'replacementString')
Grigory Kislin
quelle
0

Die oben / früher veröffentlichte Antwort, die CHAR (13) CHAR (10) Wagenrücklauf ersetzen soll:

REPLACE(REPLACE(REPLACE(MyField, CHAR(13) + CHAR(10), 'something else'), CHAR(13), 'something else'), CHAR(10), 'something else')

Kommt nie zu dem REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')Teil des Codes und gibt das unerwünschte Ergebnis von zurück:

'something else''something else'

Und NICHT das gewünschte Ergebnis einer Single:

'something else'

Dazu müsste das REPLACE-Skript als solches neu geschrieben werden:

REPLACE(REPLACE(REPLACE(MyField, CHAR(10), 'something else'), CHAR(13), 'something else'), CHAR(13) + CHAR(10), 'something else')

Wenn der Fluss zuerst die REPLACE-Anweisung 1st / Furthest Left testet, wird bei einem Fehler die nächste REPLACE-Anweisung weiter getestet.

Mike
quelle