Zamień nowy wiersz w TSQL

414

Chciałbym zastąpić (lub usunąć) znak nowej linii w łańcuchu TSQL. Jakieś pomysły?

Oczywistość

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

po prostu tego nie zrobię ...

Piotr
źródło

Odpowiedzi:

841

W rzeczywistości nowy wiersz w poleceniu SQL lub ciągu skryptu może być dowolnym z CR, LF lub CR + LF. Aby je wszystkie, potrzebujesz czegoś takiego:

SELECT REPLACE(REPLACE(@str, CHAR(13), ''), CHAR(10), '')
RBarryYoung
źródło
5
@NielsBrinch To będzie działać tak długo, jak długo będzie to jedyny rodzaj podziału linii w ciągach. Ale SQL Server obsługuje wszystkie trzy typy. W rzeczywistości, jeśli kiedykolwiek wyodrębniłeś wszystkie systemowe procedury składowane i widoki skryptów, możesz znaleźć instancje wszystkich trzech używanych przez samych Microsoft.
RBarryYoung
To zadziałało dla mnie b / c zanim zrobiłem tę kopię zmiany i wklejenie danych kolumny miałoby kursor na końcu tekstu z dwoma spacjami. Po dokonaniu tej zmiany podczas kopiowania i wklejania do notatnika kursor znajdował się bezpośrednio na końcu tekstu. To spowodowało problem dla mojego b / c w naszym graficznym interfejsie użytkownika, pojawiała się nowa linia char.
natur3
8
Jeśli typ danych kolumny to tekst, musisz najpierw rzutować na nvarchar, a następnie zastąpić WYBIERZ WYMIANĘ (WYMIANA (rzut (@str jako nvarchar (max)), CHAR (13), ''), CHAR (10), '')
akd
1
@ Slint Tak, dobra uwaga. Praktycznie rzecz biorąc, aby użyć tego z kodu klienta, należy dodać nazwę kolumny. Chociaż prawdą jest, że wiele razy możesz uciec od używania .columns[0]zamiast tego.
RBarryYoung
2
W przypadku używanej przeze mnie wersji Oracle to CHR, a nie CHAR. Na wypadek, gdyby ktoś próbował debugować z Oracle. W przeciwnym razie obowiązuje wszystko inne.
Sedona,
143
REPLACE(@string, CHAR(13) + CHAR(10), '')
Mitch Pszenica
źródło
2
To była metoda, którą wypróbowałem najpierw, ale nie działała niezawodnie dla wszystkich danych. @RBarryYoung ma to powyżej.
Mark W Dickson,
1
dzięki, musiałem zmodyfikować to trochę do pracy dla mnie, w moim przypadku jej: Wymienić (Replace (@string, Char (13), ''), Char (10), '')
user734028
36

Mogę spóźnić się na imprezę o rok, ale codziennie pracuję nad zapytaniami i MS-SQL, i mam już dość wbudowanych funkcji LTRIM () i RTRIM () (i zawsze muszę je wywoływać razem) oraz nie wychwytywania „brudnych” danych, które miały na końcu znaki nowej linii, więc zdecydowałem, że najwyższy czas, aby zaimplementować lepszą funkcję TRIM. Mile widziane opinie innych!

Zastrzeżenie : to faktycznie usuwa (zastępuje pojedynczą białą spacją) rozszerzone formy białych znaków (tabulator, wstawianie wiersza, powrót karetki itp.), Więc została zmieniona na „CleanAndTrim” z mojej oryginalnej odpowiedzi. Chodzi o to, że twój ciąg nie potrzebuje w środku takich znaków z białymi spacjami, a więc jeśli nie występują na czubku / ogonie, należy je zastąpić zwykłą spacją. Jeśli celowo zapisałeś takie znaki w swoim ciągu (powiedzmy, kolumnę danych, na której zamierzasz to uruchomić), NIE ZRÓB TO! Ulepsz tę funkcję lub napisz własną, która dosłownie usuwa te znaki z punktów końcowych ciągu, a nie z „ciała”.

Ok, teraz, gdy oświadczenie zostało zaktualizowane, oto kod.

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

Twoje zdrowie!

Kolejne zrzeczenie się odpowiedzialności : Typowym podziałem wiersza w systemie Windows jest CR + LF, więc jeśli łańcuch zawiera te znaki, możesz zastąpić je „podwójnymi” spacjami.

AKTUALIZACJA, 2016 : Nowa wersja, która daje możliwość zastąpienia znaków specjalnych spacjami innymi znakami do wyboru! Obejmuje to również komentarz i obejście dla parowania Windows CR + LF, tj. Zastępuje tę określoną parę znaków pojedynczym podstawieniem.

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
źródło
Dawni użytkownicy, zwróćcie uwagę na zmianę i wyłączenie odpowiedzialności - przepraszam za wstępne założenia dotyczące użytkowania i celu.
NateJ
1
Nowa aktualizacja! Przypadki testowe można znaleźć tutaj: sqlfiddle.com/#!6/585a2/1/0 - Wyglądało na to, że SQLFiddle dławił się podczas mojej rzeczywistej pracy przypadków testowych, więc zamiast tego zbudowałem tabelę „konstruktora zapytań dla przypadków testowych” i dajemy 9 instrukcji do skopiowania i wklejenia do własnego okna SSMS do uruchomienia (po utworzeniu oczywiście schematu, tj. funkcji i tabeli TestStrings).
NateJ
32

Nowa linia w T-SQL jest reprezentowana przez CHAR (13) i CHAR (10) (powrót karetki + przesunięcie wiersza). W związku z tym możesz utworzyć instrukcję REPLACE z tekstem, który chcesz zastąpić nowym wierszem.

REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')
Cerebrus
źródło
9
to nie jest dokładnie to samo, co zaakceptowana odpowiedź; zaakceptowana odpowiedź usuwa dowolną kombinację {13, 10}. usuwa to tylko określoną kombinację 13, a następnie 10. Nie robi to różnicy dla zakończeń linii systemu Windows, ale tutaj inne kodowanie zostanie pominięte.
Andrew Hill,
24

Aby zrobić to, co chciałaby większość ludzi, utwórz symbol zastępczy, który nie jest rzeczywistym znakiem podziału linii. Następnie możesz połączyć podejścia do:

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

W ten sposób zamieniasz tylko raz. Podejście:

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

Działa świetnie, jeśli chcesz po prostu pozbyć się znaków CRLF, ale jeśli chcesz symbol zastępczy, taki jak
czy coś, to pierwsze podejście jest nieco dokładniejsze.

wieprzowina
źródło
6

Jeśli typ danych kolumny to „ tekst ”, pojawi się komunikat o błędzie jako

Msg 8116, poziom 16, stan 1, wiersz 2 Tekst typu danych argumentu jest niepoprawny dla argumentu 1 funkcji zamiany.

W takim przypadku musisz rzucić tekst jako nvarchar, a następnie zastąpić

SELECT REPLACE(REPLACE(cast(@str as nvarchar(max)), CHAR(13), ''), CHAR(10), '')
akd
źródło
Ok, to wygląda świetnie. Teraz, co jeśli próbuję zastąpić to „! Crlf” i tak, to znak spacji po! Crlf. Problem polega na tym, że występuje to w środku łańcucha, czy mógłbym uciec z: WYBIERZ WYMIANA (WYMIANA (obsada (@str jako nvarchar (MAX)), CHAR (33), CHAR (13), CHAR (10), CHAR (32), '') czy mam to napisane niepoprawnie? Ciąg wygląda następująco: pozwala zdalnym atakującym ominąć mechanizm ochrony piaskownicy i uzyskać uprawnienia za pośrednictwem spreparowanej strony internetowej Dostęp do t! Hat jest możliwy za pomocą Internet Explorera, Focus on the słowo t! hat ... to jest moje kłopotliwe miejsce
bbcompent1
3

Jeśli masz problem polegający na tym, że chcesz usunąć tylko końcowe znaki, możesz spróbować:

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

To rozwiązało problem, który miałem z adresami, w których procedura tworzyła pole ze stałą liczbą linii, nawet jeśli te linie były puste. Aby zaoszczędzić miejsce w moim raporcie SSRS, zmniejszyłem je.

DaveX
źródło
1

Jeśli masz otwartą procedurę z użyciem sp_helptext, po prostu skopiuj cały tekst w nowym zapytaniu sql i naciśnij ctrl + h przycisk użyj wyrażenia regularnego do zamiany i umieść ^ \ n w polu znajduj zamień na puste. po więcej szczegółów sprawdź obraz. wprowadź opis zdjęcia tutaj

Rohan
źródło
1

Do rozwiązania @Cerebrus: dla H2 dla ciągów „+” nie jest obsługiwane. Więc:

REPLACE(string, CHAR(13) || CHAR(10), 'replacementString')
Grigorij Kislin
źródło
0

Odpowiedź zamieszczona powyżej / wcześniej, która została zgłoszona jako zastępująca zwrot karetki CHAR (13) CHAR (10):

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

Nigdy nie przejdzie do REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')części kodu i zwróci niechciany wynik:

'something else''something else'

I NIE pożądany wynik pojedynczego:

'something else'

Wymagałoby to przepisania skryptu REPLACE jako takiego:

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

Gdy przepływ najpierw przetestuje pierwszą / najdalszą lewą instrukcję REPLACE, to w przypadku niepowodzenia będzie kontynuować testowanie następnej instrukcji REPLACE.

Mikrofon
źródło