Sostituisci una nuova riga in TSQL


414

Vorrei sostituire (o rimuovere) un carattere newline in una stringa TSQL. Qualche idea?

L'ovvio

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

semplicemente non lo farò ...

Risposte:


843

In realtà una nuova riga in un comando SQL o stringa di script può essere una qualsiasi di CR, LF o CR + LF. Per ottenerli tutti, hai bisogno di qualcosa del genere:

SELECT REPLACE(REPLACE(@str, CHAR(13), ''), CHAR(10), '')

5
@NielsBrinch Funzionerà bene fintanto che è l'unico tipo di interruzione di linea nelle stringhe. Ma SQL Server supporta tutti e tre i tipi. In effetti, se hai mai estratto tutte le procedure archiviate di sistema e le visualizzazioni con script, puoi trovare istanze di tutti e tre come utilizzate da Microsoft stesso.
RBarryYoung,

Questo ha funzionato per me in b / c prima di apportare questa modifica alla copia e incollare i dati della colonna avrebbe il cursore alla fine del testo con due spazi. Dopo aver apportato questa modifica, copiando e incollando nel blocco note il cursore si trovava direttamente alla fine del testo. Stava causando un problema per me b / c nella nostra interfaccia grafica del front-end che stava mostrando il nuovo carattere di linea.
natur3

8
Se il tipo di dati della colonna è testo, devi prima eseguire il cast su nvarchar, quindi sostituire SELEZIONA SOSTITUISCI (SOSTITUISCI (cast (@str as nvarchar (max)), CHAR (13), ''), CHAR (10), '')
Akd

1
@Slint Sì, buon punto. In pratica, per utilizzare questo dal codice client è necessario aggiungere un nome di colonna. Anche se è vero che molte volte puoi cavartela usando .columns[0]invece.
RBarryYoung,

2
Per la versione di Oracle che sto usando, l'affermazione è CHR, non CHAR. Nel caso in cui qualcuno stia cercando di eseguire il debug da Oracle. Altrimenti, tutto il resto si applica.
Sedona

143
REPLACE(@string, CHAR(13) + CHAR(10), '')

2
Questo è stato il metodo che ho provato per primo, ma non ha funzionato in modo affidabile per tutti i dati. @RBarryYoung ce l'ha proprio sopra.
Mark W Dickson,

1
grazie, ho dovuto modificarlo un po 'per funzionare per me, nel mio caso è: replace (REPLACE (@string, CHAR (13),' '), CHAR (10),' ')
user734028

36

Potrei essere in ritardo di un anno alla festa, ma lavoro ogni giorno su query e MS-SQL e mi sono stancato delle funzioni integrate LTRIM () e RTRIM () (e devo sempre chiamarle insieme), e di non acquisire dati "sporchi" che alla fine avevano nuove righe, quindi ho deciso che era giunto il momento di implementare una migliore funzione TRIM. Gradirei un feedback tra pari!

Dichiarazione di non responsabilità : in realtà rimuove (sostituisce con un singolo spazio bianco) forme estese di spazio bianco (tabulazione, avanzamento riga, ritorno a capo, ecc.), Quindi è stato rinominato "CleanAndTrim" dalla mia risposta originale. L'idea qui è che la tua stringa non abbia bisogno di caratteri extra-bianchi al suo interno, quindi se non si presentano in testa / coda, dovrebbero essere sostituiti con uno spazio semplice. Se hai memorizzato intenzionalmente tali caratteri nella tua stringa (diciamo, la tua colonna di dati su cui stai per eseguire questo), NON FARLO! Migliora questa funzione o scrivine una tua che rimuove letteralmente quei caratteri dagli endpoint della stringa, non dal "corpo".

Bene, ora che il disclaimer è aggiornato, ecco il codice.

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

Saluti!

Un altro disclaimer : la tua tipica interruzione di linea di Windows è CR + LF, quindi se la tua stringa li contiene, finiresti per sostituirli con spazi "doppi".

AGGIORNAMENTO, 2016 : una nuova versione che ti dà la possibilità di sostituire quei caratteri degli spazi speciali con altri personaggi a tua scelta! Ciò include anche commenti e soluzioni alternative per l'accoppiamento CR + LF di Windows, ovvero sostituisce quella specifica coppia di caratteri con una singola sostituzione.

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

Utenti precedenti, si prega di notare la modifica e la dichiarazione di non responsabilità - e mi scuso per le ipotesi iniziali sull'uso e lo scopo.
NateJ,

1
Nuovo aggiornamento! I casi di test possono essere trovati qui: sqlfiddle.com/#!6/585a2/1/0 - SQLFiddle sembrava soffocare sulla mia effettiva esecuzione dei casi di test, quindi invece ho creato una tabella "builder test-case query" e ti dà le 9 istruzioni da copiare e incollare nella tua finestra SSMS da eseguire (dopo aver creato lo schema ovviamente, cioè la funzione e la tabella TestStrings).
NateJ,

32

La Newline in T-SQL è rappresentata da CHAR (13) e CHAR (10) (ritorno a capo + avanzamento riga). Di conseguenza, è possibile creare un'istruzione REPLACE con il testo con cui si desidera sostituire la nuova riga.

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

9
questa non è esattamente la stessa della risposta accettata; la risposta accettata rimuove qualsiasi combinazione di {13, 10}. questo rimuove solo la combinazione specifica di 13 e 10. Non fa differenza per le terminazioni di linea di Windows, ma qui mancherà altra codifica.
Andrew Hill,

24

Per fare ciò che la maggior parte delle persone vorrebbe, crea un segnaposto che non sia un vero personaggio che interrompe la linea. Quindi puoi effettivamente combinare gli approcci per:

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

In questo modo si sostituisce una sola volta. L'approccio di:

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

Funziona alla grande se vuoi semplicemente sbarazzarti dei personaggi CRLF, ma se vuoi un segnaposto, come
o qualcosa del genere, il primo approccio è un po 'più preciso.


6

Se il tipo di dati della colonna è " testo ", verrà visualizzato un messaggio di errore come

Messaggio 8116, livello 16, stato 1, riga 2 Il testo del tipo di dati dell'argomento non è valido per l'argomento 1 della funzione di sostituzione.

In questo caso è necessario eseguire il cast del testo come nvarchar e quindi sostituirlo

SELECT REPLACE(REPLACE(cast(@str as nvarchar(max)), CHAR(13), ''), CHAR(10), '')

Ok, sembra fantastico. Ora, cosa succede se quello che sto cercando di sostituire è "! Crlf" e sì, questo è un personaggio spaziale dopo il! Crlf. La preoccupazione è che ciò si verifichi nel mezzo della stringa, potrei cavarmela con: SELECT REPLACE (REPLACE (cast (@str as nvarchar (MAX)), CHAR (33), CHAR (13), CHAR (10), CHAR (32), '') o ho scritto in modo errato? La stringa è simile alla seguente: consentire agli aggressori remoti di bypassare un meccanismo di protezione sandbox e ottenere privilegi tramite un sito Web predisposto a cui si accede con Internet Explorer, Focus sul parola t! hat ... questo è il mio punto di disturbo
bbcompent1

3

Se hai un problema in cui desideri rimuovere solo i caratteri finali , puoi provare questo:

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

Ciò ha risolto un problema che avevo con gli indirizzi in cui una procedura creava un campo con un numero fisso di linee, anche se quelle linee erano vuote. Per risparmiare spazio nel mio rapporto SSRS, li ho ridotti.


1

Se hai una procedura aperta con l'utilizzo di sp_helptext, copia semplicemente tutto il testo nella nuova query sql e premi il tasto ctrl + h usa l'espressione regolare per sostituire e metti ^ \ n nel campo Trova sostituisci con vuoto. per maggiori dettagli controlla l'immagine. inserisci qui la descrizione dell'immagine


1

Alla soluzione @Cerebrus: per H2 per le stringhe "+" non è supportato. Così:

REPLACE(string, CHAR(13) || CHAR(10), 'replacementString')

0

La risposta postata sopra / precedente che è stata segnalata in sostituzione di CHAR (13) CHAR (10) ritorno a capo:

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

Non arriverà mai alla REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')parte del codice e restituirà il risultato indesiderato di:

'something else''something else'

E NON il risultato desiderato di un singolo:

'something else'

Ciò richiederebbe la riscrittura dello script REPLACE come tale:

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

Quando il flusso verifica prima l'istruzione REPLACE 1a / Più a sinistra, quindi in caso di errore continuerà a provare l'istruzione REPLACE successiva.

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.