Reemplazar una nueva línea en TSQL

414

Me gustaría reemplazar (o eliminar) un carácter de nueva línea en una cadena TSQL. ¿Algunas ideas?

Lo obvio

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

simplemente no lo haré ...

Peter
fuente

Respuestas:

843

En realidad, una nueva línea en un comando SQL o cadena de script puede ser cualquiera de CR, LF o CR + LF. Para obtenerlos todos, necesita algo como esto:

SELECT REPLACE(REPLACE(@str, CHAR(13), ''), CHAR(10), '')
RBarryYoung
fuente
55
@NielsBrinch Eso funcionará bien siempre que sea el único tipo de salto de línea en sus cadenas. Pero SQL Server admite los tres tipos. De hecho, si alguna vez extrajo todos los procedimientos almacenados del sistema y las vistas con guiones, puede encontrar instancias de los tres tal como los utilizó Microsoft.
RBarryYoung
Esto funcionó para mí b / c antes de hacer esta copia de cambio y pegar los datos de la columna tendría el cursor al final del texto con dos espacios. Después de hacer este cambio, copiar y pegar en el bloc de notas tenía el cursor directamente al final del texto. Estaba causando un problema para mí b / c en nuestra interfaz gráfica de usuario frontal que mostraba la nueva línea char.
natur3
8
Si el tipo de datos de la columna es texto, primero debe convertir a nvarchar y luego reemplazar SELECT REPLACE (REPLACE (cast (@str as nvarchar (max)), CHAR (13), ''), CHAR (10), '')
akd
1
@Slint Sí, buen punto. En términos prácticos, para usar esto desde el código del cliente, debe agregar un nombre de columna. Aunque es cierto que muchas veces puedes salirte con la tuya .columns[0].
RBarryYoung
2
Para la versión de Oracle que estoy usando, la declaración es CHR, no CHAR. En caso de que alguien esté tratando de depurar desde Oracle. De lo contrario, todo lo demás se aplica.
Sedona
143
REPLACE(@string, CHAR(13) + CHAR(10), '')
Trigo Mitch
fuente
2
Este fue el método que probé primero, pero no funcionó de manera confiable para todos los datos. @RBarryYoung lo tiene justo arriba.
Mark W Dickson el
1
gracias, tuve que modificar esto un poco para que funcione para mí, en mi caso es: replace (REPLACE (@string, CHAR (13), ''), CHAR (10), '')
user734028
36

Puede que llegue un año tarde a la fiesta, pero trabajo en consultas y MS-SQL todos los días, y me cansé de las funciones integradas LTRIM () y RTRIM () (y siempre tengo que llamarlas juntas), y de no capturar datos 'sucios' que tenían nuevas líneas al final, así que decidí que era hora de implementar una mejor función TRIM. Agradecería los comentarios de los compañeros!

Descargo de responsabilidad : esto en realidad elimina (reemplaza con un solo espacio en blanco) formas extendidas de espacio en blanco (tabulación, avance de línea, retorno de carro, etc.), por lo que ha sido renombrado como "CleanAndTrim" de mi respuesta original. La idea aquí es que su cadena no necesita caracteres de espacios en blanco especiales adicionales dentro de ella, por lo que si no aparecen en la cabeza / cola, deberían reemplazarse con un espacio simple. Si almacenó dichos caracteres a propósito en su cadena (por ejemplo, su columna de datos en la que está a punto de ejecutar esto), ¡NO LO HAGA! Mejore esta función o escriba la suya propia, que literalmente elimina esos caracteres de los puntos finales de la cadena, no del 'cuerpo'.

Bien, ahora que el descargo de responsabilidad está actualizado, aquí está el código.

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

¡Salud!

Otro descargo de responsabilidad : su salto de línea típico de Windows es CR + LF, por lo que si su cadena contiene esos, terminaría reemplazándolos con espacios "dobles".

ACTUALIZACIÓN, 2016 : ¡Una nueva versión que le da la opción de reemplazar esos caracteres de espacios en blanco especiales con otros caracteres de su elección! Esto también incluye comentarios y la solución alternativa para el emparejamiento de Windows CR + LF, es decir, reemplaza ese par de caracteres específico con una sola sustitución.

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
fuente
Usuarios anteriores, tenga en cuenta el cambio y la exención de responsabilidad, y me disculpo por las suposiciones iniciales sobre el uso y el propósito.
NateJ
1
¡Nueva actualización! Los casos de prueba se pueden encontrar aquí: sqlfiddle.com/#!6/585a2/1/0 - SQLFiddle pareció ahogarse en mi ejecución real de los casos de prueba, así que en su lugar, construí una tabla de "generador de consultas de casos de prueba" & le da las 9 declaraciones para copiar y pegar en su propia ventana SSMS para ejecutar (después de crear el esquema, por supuesto, es decir, la función y la tabla TestStrings).
NateJ
32

La nueva línea en T-SQL está representada por CHAR (13) y CHAR (10) (retorno de carro + avance de línea). En consecuencia, puede crear una instrucción REPLACE con el texto con el que desea reemplazar la nueva línea.

REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')
Cerebro
fuente
99
esto no es lo mismo que la respuesta aceptada; la respuesta aceptada elimina cualquier combinación de {13, 10}. esto solo elimina la combinación específica de 13 y luego 10. No hace una diferencia para las terminaciones de línea de Windows, pero aquí se perderá otra codificación.
Andrew Hill
24

Para hacer lo que la mayoría de las personas desearía, cree un marcador de posición que no sea un carácter de salto de línea real. Entonces puedes combinar los enfoques para:

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

De esta manera, lo reemplaza solo una vez. El enfoque de:

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

Funciona muy bien si solo desea deshacerse de los caracteres CRLF, pero si desea un marcador de posición, como
o algo así, entonces el primer enfoque es un poco más preciso.

Porkandcheese
fuente
6

Si el tipo de datos de su columna es ' texto ', recibirá un mensaje de error como

Mensaje 8116, Nivel 16, Estado 1, Línea 2 El texto del tipo de datos de argumento no es válido para el argumento 1 de la función de reemplazo.

En este caso, debe convertir el texto como nvarchar y luego reemplazar

SELECT REPLACE(REPLACE(cast(@str as nvarchar(max)), CHAR(13), ''), CHAR(10), '')
akd
fuente
Ok, esto se ve genial. Ahora, ¿qué pasa si lo que estoy tratando de reemplazar es "! Crlf" y sí, ese es un carácter de espacio después de! Crlf. La preocupación es que esto ocurre en el medio de la cadena, ¿podría salirse con la suya ?: SELECT REPLACE (REPLACE (cast (@str as nvarchar (MAX)), CHAR (33), CHAR (13), CHAR (10), CHAR (32), '') o ¿tengo esto escrito incorrectamente? La cadena tiene este aspecto: permitir a los atacantes remotos eludir un mecanismo de protección sandbox y obtener privilegios a través de un sitio web diseñado al que se accede con Internet Explorer, Focus on the palabra t! sombrero ... ese es mi punto problemático.
bbcompent1
3

Si tiene un problema en el que solo desea eliminar los caracteres finales , puede intentar esto:

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

Esto resolvió un problema que tenía con las direcciones donde un procedimiento creaba un campo con un número fijo de líneas, incluso si esas líneas estaban vacías. Para ahorrar espacio en mi informe SSRS, los reduje.

DaveX
fuente
1

Si tiene un procedimiento abierto con el uso de sp_helptext, simplemente copie todo el texto en la nueva consulta sql y presione el botón ctrl + h, use la expresión regular para reemplazar y coloque ^ \ n en el campo de búsqueda reemplazar con espacio en blanco. para más detalles verifique la imagen. ingrese la descripción de la imagen aquí

Rohan
fuente
1

Para la solución @Cerebrus: para H2 para cadenas "+" no es compatible. Entonces:

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

La respuesta publicada anteriormente / anteriormente que se informó que reemplaza CHAR (13) CHAR (10) retorno de carro:

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

Nunca llegará a la REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')parte del código y devolverá el resultado no deseado de:

'something else''something else'

Y NO el resultado deseado de un solo:

'something else'

Eso requeriría que el script REPLACE se reescriba como tal:

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

Como el flujo prueba primero la primera instrucción REPLACE izquierda / más alejada, luego, si falla, continuará probando la siguiente instrucción REPLACE.

Miguel
fuente