Substituir uma nova linha no TSQL

414

Gostaria de substituir (ou remover) um caractere de nova linha em uma string TSQL. Alguma ideia?

O óbvio

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

simplesmente não vai fazer isso ...

Pedro
fonte

Respostas:

843

Na verdade, uma nova linha em um comando SQL ou sequência de scripts pode ser qualquer um de CR, LF ou CR + LF. Para obtê-los todos, você precisa de algo como isto:

SELECT REPLACE(REPLACE(@str, CHAR(13), ''), CHAR(10), '')
RBarryYoung
fonte
5
@ NielsBrinch Isso funcionará bem, desde que seja o único tipo de quebra de linha em suas strings. Mas o SQL Server oferece suporte aos três tipos. De fato, se você já extraiu todos os procedimentos armazenados do sistema e exibições com script, poderá encontrar instâncias dos três conforme usadas pela própria Microsoft.
RBarryYoung
Isso funcionou para mim b / c antes de eu fazer essa cópia de alteração e colar os dados da coluna teria o cursor no final do texto com dois espaços. Depois de fazer essa alteração, copiando e colando no bloco de notas, o cursor ficava diretamente no final do texto. Isso estava causando um problema para mim, porque na nossa interface gráfica front-end, o novo caracter de linha estava aparecendo.
natur3
8
Se o tipo de dados da coluna for texto, primeiro você precisará converter para nvarchar e substituir SELECT REPLACE (REPLACE (converter (@str como nvarchar (max)), CHAR (13), ''), CHAR (10), '')
AKD
1
@ Slint Sim, bom ponto. Na prática, para usar isso no código do cliente, você deve adicionar um nome de coluna. Embora seja verdade que muitas vezes você pode se safar do uso .columns[0].
RBarryYoung
2
Para a versão do Oracle que estou usando, a instrução é CHR, não CHAR. Apenas no caso de alguém estar tentando depurar do Oracle. Caso contrário, tudo o resto se aplica.
Sedona
143
REPLACE(@string, CHAR(13) + CHAR(10), '')
Mitch Wheat
fonte
2
Este foi o método que tentei primeiro, mas não funcionou de forma confiável para todos os dados. @RBarryYoung está logo acima.
Mark W Dickson
1
obrigado, eu tive que modificar isso um pouco para trabalhar para mim, no meu caso é: replace (REPLACE (@string, CHAR (13), ''), CHAR (10), '')
user734028
36

Talvez eu esteja atrasado um ano para a festa, mas trabalho com consultas e MS-SQL todos os dias e me cansei das funções internas LTRIM () e RTRIM () (e sempre tenho que chamá-las juntas) e de não pegar dados "sujos" que tinham novas linhas no final, então decidi que estava na hora de implementar uma função TRIM melhor. Gostaria de receber feedback de colegas!

Isenção de responsabilidade : isso na verdade remove (substitui por um único espaço em branco) as formas estendidas de espaço em branco (guia, alimentação de linha, retorno de carro etc.), por isso foi renomeado como "CleanAndTrim" da minha resposta original. A idéia aqui é que sua string não precise de caracteres especiais em branco em branco e, se não ocorrerem na cabeça / cauda, ​​eles deverão ser substituídos por um espaço simples. Se você intencionalmente armazenou esses caracteres na sua string (digamos, na sua coluna de dados que você está prestes a executá-la), NÃO FAÇA! Melhore essa função ou escreva você mesmo que literalmente remove esses caracteres dos pontos finais da string, não do 'corpo'.

Ok, agora que o aviso foi atualizado, aqui está o 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

Felicidades!

Outro aviso de isenção de responsabilidade : sua quebra de linha típica do Windows é CR + LF; portanto, se sua string contiver esses itens, você poderá substituí-los por espaços "duplos".

ATUALIZAÇÃO, 2016 : Uma nova versão que oferece a opção de substituir esses caracteres de espaço em branco especial por outros caracteres de sua escolha! Isso também inclui comentários e a solução alternativa para o emparelhamento Windows CR + LF, ou seja, substitui esse par de caracteres específico por uma única substituição.

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
fonte
Usuários anteriores, observe as alterações e isenções de responsabilidade - e peço desculpas pelas suposições iniciais sobre uso e finalidade.
NateJ 23/03
1
Nova atualização! Os casos de teste podem ser encontrados aqui: sqlfiddle.com/#!6/585a2/1/0 - O SQLFiddle parecia engasgar com a execução real dos casos de teste. Em vez disso, criei uma tabela "construtor de consultas de casos de teste" e forneça as 9 instruções para copiar e colar em sua própria janela do SSMS para executar (depois de criar o esquema, é claro, ou seja, a função e a tabela TestStrings).
NateJ
32

A nova linha no T-SQL é representada por CHAR (13) e CHAR (10) (retorno de carro + avanço de linha). Assim, você pode criar uma instrução REPLACE com o texto que deseja substituir a nova linha.

REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')
Cerebrus
fonte
9
isso não é exatamente o mesmo que a resposta aceita; a resposta aceita remove qualquer combinação de {13, 10}. isso remove apenas a combinação específica de 13 e 10. Não difere as terminações de linha do Windows, mas outras codificações serão perdidas aqui.
Andrew Hill
24

Para fazer o que a maioria das pessoas deseja, crie um espaço reservado que não seja um caractere de quebra de linha real. Em seguida, você pode realmente combinar as abordagens para:

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

Dessa forma, você substitui apenas uma vez. A abordagem de:

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

Funciona muito bem se você quiser se livrar dos caracteres CRLF, mas se desejar um espaço reservado, como
algo assim, a primeira abordagem será um pouco mais precisa.

porkandcheese
fonte
6

Se o tipo de dados da sua coluna for ' texto ', você receberá uma mensagem de erro como

Msg 8116, nível 16, estado 1, linha 2 O texto do tipo de dados do argumento é inválido para o argumento 1 da função de substituição.

Nesse caso, você precisa converter o texto como nvarchar e substituir

SELECT REPLACE(REPLACE(cast(@str as nvarchar(max)), CHAR(13), ''), CHAR(10), '')
akd
fonte
Ok, isso parece ótimo. Agora, e se o que estou tentando substituir for "! Crlf" e sim, esse é um caractere de espaço após o! Crlf. A preocupação é que isso ocorra no meio da string, eu poderia me safar com: SELECT REPLACE (REPLACE (cast (@str como nvarchar (MAX)), CHAR (33), CHAR (13), CHAR (10), CHAR (32), '') ou eu escrevi isso incorretamente? A cadeia é assim: permite que atacantes remotos ignorem um mecanismo de proteção de sandbox e obtenham privilégios por meio de um site criado que é acessado com o Internet Explorer, Concentre-se no ! palavra t chapéu ... esse é o meu ponto de conflito.
bbcompent1
3

Se você tiver um problema em que deseja remover apenas os caracteres finais , tente o seguinte:

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

Isso resolveu um problema que tive com endereços em que um procedimento criava um campo com um número fixo de linhas, mesmo que essas linhas estivessem vazias. Para economizar espaço no meu relatório do SSRS, eu os reduzi.

DaveX
fonte
1

Se você tiver um procedimento aberto com o uso de sp_helptext, basta copiar todo o texto na nova consulta sql e pressionar ctrl + h. Use a expressão regular para substituir e coloque ^ \ n no campo Localizar, substitua por branco. para obter mais detalhes, verifique a imagem. insira a descrição da imagem aqui

Rohan
fonte
1

Para a solução @Cerebrus: para H2 para as seqüências de caracteres "+" não há suporte. Assim:

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

A resposta postada acima / anteriormente relatada para substituir o retorno de carro CHAR (13) CHAR (10):

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

Nunca REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')chegará à parte do código e retornará o resultado indesejado de:

'something else''something else'

E NÃO o resultado desejado de um único:

'something else'

Isso exigiria que o script REPLACE fosse reescrito da seguinte maneira:

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

Como o fluxo testa primeiro a instrução REPLACE da 1ª / mais à esquerda, em caso de falha, continuará a testar a próxima instrução REPLACE.

Mike
fonte