Remplacer une nouvelle ligne dans TSQL

414

Je voudrais remplacer (ou supprimer) un caractère de nouvelle ligne dans une chaîne TSQL. Des idées?

L'évident

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

ne le fera tout simplement pas ...

Peter
la source

Réponses:

843

En fait, une nouvelle ligne dans une chaîne de commande ou de script SQL peut être n'importe laquelle de CR, LF ou CR + LF. Pour les obtenir tous, vous avez besoin de quelque chose comme ceci:

SELECT REPLACE(REPLACE(@str, CHAR(13), ''), CHAR(10), '')
RBarryYoung
la source
5
@NielsBrinch Cela fonctionnera bien tant que c'est le seul type de saut de ligne dans vos chaînes. Mais SQL Server prend en charge les trois types. En fait, si vous avez déjà extrait toutes les procédures stockées du système et les vues de script, vous pouvez trouver des instances des trois telles qu'utilisées par Microsoft.
RBarryYoung
Cela a fonctionné pour moi b / c avant de faire cette copie de modification et de coller les données de la colonne aurait le curseur à la fin du texte avec deux espaces. Après avoir effectué ce changement en copiant et collant dans le bloc-notes, le curseur se trouvait directement à la fin du texte. Cela causait un problème pour moi b / c dans notre interface graphique frontale, le nouveau caractère de ligne apparaissait.
natur3
8
Si le type de données de la colonne est du texte, vous devez d'abord convertir en nvarchar puis remplacer SELECT REPLACE (REPLACE (cast (@str as nvarchar (max)), CHAR (13), ''), CHAR (10), '')
akd
1
@ Slint Oui, bon point. En pratique, pour utiliser cela à partir du code client, vous devez ajouter un nom de colonne. Bien qu'il soit vrai que la plupart du temps, vous pouvez vous en tirer à la .columns[0]place.
RBarryYoung
2
Pour la version d'Oracle que j'utilise, la déclaration est CHR, pas CHAR. Juste au cas où quelqu'un essaie de déboguer depuis Oracle. Sinon, tout le reste s'applique.
Sedona
143
REPLACE(@string, CHAR(13) + CHAR(10), '')
Blé Mitch
la source
2
C'est la méthode que j'ai essayée en premier, mais elle n'a pas fonctionné de manière fiable pour toutes les données. @RBarryYoung l'a juste au-dessus.
Mark W Dickson
1
merci, j'ai dû modifier cela un peu pour que ça marche pour moi, dans mon cas c'est: replace (REPLACE (@string, CHAR (13), ''), CHAR (10), '')
user734028
36

J'ai peut-être un an de retard pour la fête, mais je travaille tous les jours sur les requêtes et MS-SQL, et je me suis fatigué des fonctions intégrées LTRIM () & RTRIM () (et toujours avoir à les appeler ensemble), et de ne pas attraper les données «sales» qui avaient des nouvelles lignes à la fin, j'ai donc décidé qu'il était grand temps de mettre en œuvre une meilleure fonction TRIM. J'accueillerais les commentaires des pairs!

Avertissement : cela supprime en fait (remplace par un seul espace blanc) les formes étendues d'espaces blancs (tabulation, saut de ligne, retour chariot, etc.), il a donc été renommé "CleanAndTrim" de ma réponse d'origine. L'idée ici est que votre chaîne n'a pas besoin de ces caractères d'espaces spéciaux supplémentaires à l'intérieur, et donc s'ils ne se produisent pas en tête / queue, ils doivent être remplacés par un espace simple. Si vous avez délibérément stocké de tels caractères dans votre chaîne (par exemple, votre colonne de données sur laquelle vous êtes sur le point de l'exécuter), NE LE FAITES PAS! Améliorez cette fonction ou écrivez la vôtre qui supprime littéralement ces caractères des points de terminaison de la chaîne, pas du «corps».

Bon, maintenant que l'avertissement est mis à jour, voici le 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

À votre santé!

Un autre avertissement : votre saut de ligne Windows typique est CR + LF, donc si votre chaîne en contient, vous finirez par les remplacer par des espaces "doubles".

MISE À JOUR, 2016 : Une nouvelle version qui vous donne la possibilité de remplacer ces caractères d'espaces spéciaux par d' autres caractères de votre choix! Cela inclut également les commentaires et la solution de contournement pour l'appariement Windows CR + LF, c'est-à-dire remplace cette paire de caractères spécifique par une seule substitution.

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
la source
Anciens utilisateurs, veuillez noter le changement et la clause de non-responsabilité - et je m'excuse pour les hypothèses initiales sur l'utilisation et le but.
NateJ
1
Nouvelle mise à jour! Les cas de test peuvent être trouvés ici: sqlfiddle.com/#!6/585a2/1/0 - SQLFiddle a semblé s'étrangler sur mon exécution réelle des cas de test, donc à la place, j'ai construit une table "générateur de requêtes de cas de test" & vous donner les 9 instructions à copier-coller dans votre propre fenêtre SSMS à exécuter (après avoir bien sûr créé le schéma, c'est-à-dire la fonction et la table TestStrings).
NateJ
32

Le Newline dans T-SQL est représenté par CHAR (13) & CHAR (10) (retour chariot + saut de ligne). Par conséquent, vous pouvez créer une instruction REPLACE avec le texte avec lequel vous souhaitez remplacer la nouvelle ligne.

REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')
Cerebrus
la source
9
ce n'est pas tout à fait la même chose que la réponse acceptée; la réponse acceptée supprime toute combinaison de {13, 10}. cela supprime uniquement la combinaison spécifique de 13 puis 10. Cela ne fait pas de différence pour les fins de ligne Windows, mais d'autres encodages seront manqués ici.
Andrew Hill
24

Pour faire ce que la plupart des gens voudraient, créez un espace réservé qui n'est pas un véritable caractère de saut de ligne. Ensuite, vous pouvez réellement combiner les approches pour:

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

De cette façon, vous ne remplacez qu'une seule fois. L'approche de:

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

Fonctionne très bien si vous voulez simplement vous débarrasser des caractères CRLF, mais si vous voulez un espace réservé, comme
ou quelque chose, la première approche est un peu plus précise.

porkandcheese
la source
6

Si le type de données de votre colonne est « texte », vous obtiendrez un message d'erreur

Msg 8116, niveau 16, état 1, ligne 2 Le texte du type de données d'argument n'est pas valide pour l'argument 1 de la fonction de remplacement.

Dans ce cas, vous devez convertir le texte en nvarchar, puis remplacer

SELECT REPLACE(REPLACE(cast(@str as nvarchar(max)), CHAR(13), ''), CHAR(10), '')
akd
la source
Ok, ça a l'air super. Maintenant, que se passe-t-il si ce que j'essaye de remplacer est "! Crlf" et oui c'est un caractère espace après le! Crlf. Le problème est que cela se produit au milieu de la chaîne, pourrais-je m'en tirer avec: SELECT REPLACE (REPLACE (cast (@str as nvarchar (MAX)), CHAR (33), CHAR (13), CHAR (10), CHAR (32), '') ou ai-je mal écrit? La chaîne ressemble à ceci: autorisez les attaquants distants à contourner un mécanisme de protection de bac à sable et à obtenir des privilèges via un site Web spécialement conçu. L'accès à Internet Explorer, Focus on the mot t! chapeau ... c'est mon problème
bbcompent1
3

Si vous avez un problème où vous souhaitez uniquement supprimer les caractères de fin , vous pouvez essayer ceci:

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

Cela a résolu un problème que j'avais avec les adresses où une procédure créait un champ avec un nombre fixe de lignes, même si ces lignes étaient vides. Pour économiser de l'espace dans mon rapport SSRS, je les ai coupés.

DaveX
la source
1

Si vous avez une procédure ouverte avec l'utilisation de sp_helptext, copiez simplement tout le texte dans la nouvelle requête sql et appuyez sur le bouton ctrl + h. Utilisez l'expression régulière pour remplacer et mettez ^ \ n dans le champ de recherche remplacer par vide. pour plus de détails, vérifiez l'image. entrez la description de l'image ici

Rohan
la source
1

Vers la solution @Cerebrus: pour H2 pour les chaînes "+" n'est pas pris en charge. Donc:

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

La réponse affichée ci-dessus / plus tôt qui a été signalée pour remplacer CHAR (13) CHAR (10) retour chariot:

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

N'atteindra jamais la REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')partie du code et renverra le résultat indésirable de:

'something else''something else'

Et PAS le résultat souhaité d'un seul:

'something else'

Cela nécessiterait que le script REPLACE soit réécrit en tant que tel:

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

Comme le flux teste d'abord l'instruction REPLACE 1ère / la plus à gauche, puis en cas d'échec continuera de tester l'instruction REPLACE suivante.

Mike
la source