Jak wstawić podział wiersza w łańcuchu VARCHAR / NVARCHAR programu SQL Server

560

Nie widziałem podobnych pytań na ten temat i musiałem to zbadać pod kątem czegoś, nad czym teraz pracuję. Pomyślałem, że opublikuję odpowiedź na to pytanie, gdyby ktoś inny miał to samo pytanie.

Mark Struziński
źródło
8
Aby przetestować dane wyjściowe, jeśli używasz SSMS, upewnij się, że opcja Zachowaj CR / LF podczas kopiowania lub zapisywania jest zaznaczona, w przeciwnym razie wszystkie wklejone wyniki utracą linię. Znajdziesz to w ustawieniach, wynikach zapytań, serwerze SQL, wynikach do siatki.
Stefanos Zilellis
1
@StefanosZilellis i pamiętaj, aby otworzyć nowe okno zapytania, aby zmiany ustawień zostały wprowadzone.
Don Cheadle

Odpowiedzi:

594

char(13)jest CR. W przypadku łamania linii w stylu DOS / Windows CRLFchcesz char(13)+char(10):

'This is line 1.' + CHAR(13)+CHAR(10) + 'This is line 2.'
Sören Kuklau
źródło
28
char (13) + char (10) nie działał dla mnie w systemie Windows. Właśnie użyłem char (10)
nima,
6
@Nima: Niektóre aplikacje będą używać jednej lub drugiej lub obu do wyświetlenia nowej linii, jednak wiele aplikacji, na które możesz wyprowadzić ten tekst, będzie wymagało, aby obie linie pojawiały się kolejno, aby oznaczać nową linię. Używanie obu jest bezpieczne. Możesz tutaj wymienić listę aplikacji, dla których nie działa. Wolę osobno wartości szesnastkowe CHAR (0x0D) + CHAR (0x0A), ale każdą własną.
MikeTeeVee
2
Z powodzeniem zastosowałem tę metodę, ale napotkałem na problem: gdy masz więcej niż 480 +, SQL Server zacznie narzekać, że twoje zapytanie jest zbyt głęboko zagnieżdżone. Moim rozwiązaniem było zamiast tego użyć odpowiedzi Roba Coopera, ale ze znacznie dłuższym i bardziej niejasnym tokenem.
Marcus Downing
5
Podanie \ r \ n oznaczałoby potwierdzenie, że istnieją wyrażenia regularne oraz że użytkownicy są w stanie je zrozumieć i używać.
wwmbes
10
@HBlackorby \ ri \ n wyprzedzają Java-cokolwiek o dziesięciolecia, używając ich w C; i są standardem w Pythonie, PHP, Ruby, C ++, C # itp.
Uueerdo,
285

Znalazłem odpowiedź tutaj: http://blog.sqlauthority.com/2007/08/22/sql-server-t-sql-script-to-insert-carriage-return-and-new-line-feed-in- kod/

Po prostu konkatenujesz ciąg i wstawiasz miejsce, w CHAR(13)którym chcesz łamać linię.

Przykład:

DECLARE @text NVARCHAR(100)
SET @text = 'This is line 1.' + CHAR(13) + 'This is line 2.'
SELECT @text

Spowoduje to wydrukowanie następujących elementów:

To jest linia 1.
To jest linia 2.

Mark Struziński
źródło
11
AKTUALIZACJA: zapomnij. Wstawia się dobrze. To studio zarządzania, które zastępuje tabulatory i znaki nowej linii spacjami dla widoczności
Daniel Dolz
12
Wygląda na to, że potrzebujesz PRINT @text zamiast SELECT, aby uzyskać ten wynik.
QMaster
3
BTW: Możesz także użyć, NCHAR(0x1234)aby uzyskać znak Unicode. Nie jest konieczne wstawianie podziałów linii, ale może się przydać, jeśli trzeba wstawić / wyszukać znaki Unicode.
Paul Groke
3
W SQL Server 2016 widzę, że drukuje dwa wiersze tylko wtedy, gdy używam printzamiast select, takich jak:DECLARE @text NVARCHAR(100); SET @text = 'This is line 1.' + CHAR(13) + 'This is line 2.'; print @text;
devinbost
7
Aby przetestować dane wyjściowe, jeśli używasz SSMS, upewnij się, że opcja Zachowaj CR / LF podczas kopiowania lub zapisywania jest zaznaczona, w przeciwnym razie wszystkie wklejone wyniki utracą linię. Znajdziesz to w ustawieniach, wynikach zapytań, serwerze SQL, wynikach do siatki.
Don Cheadle
81

Innym sposobem na to jest:

INSERT CRLF SELECT 'fox 
jumped'

Oznacza to, że po prostu wstawienie podziału wiersza w zapytaniu podczas pisania spowoduje dodanie podobnego podziału do bazy danych. Działa to w SQL Server Management studio i Query Analyzer. Wierzę, że to zadziała również w języku C #, jeśli użyjesz znaku @ na ciągach.

string str = @"INSERT CRLF SELECT 'fox 
    jumped'"
Frank V.
źródło
14
Innymi słowy, składnia języka SQL pozwala po prostu na nieprzetworzone wstawianie wierszy w literałach ciągów. Działa w ten sposób we wszystkich silnikach, które wypróbowałem (SQL Server, Oracle, MySQL, PostgreSQL i SQLite).
Álvaro González
czasami to losowo przestaje działać, jeśli używasz go w procedurach przechowywanych
DaFi4,
25

Uruchom to w SSMS, pokazuje, jak podziały wiersza w samym SQL stają się częścią wartości ciągu obejmujących linie:

PRINT 'Line 1
Line 2
Line 3'
PRINT ''

PRINT 'How long is a blank line feed?'
PRINT LEN('
')
PRINT ''

PRINT 'What are the ASCII values?'
PRINT ASCII(SUBSTRING('
',1,1))
PRINT ASCII(SUBSTRING('
',2,1))

Wynik:
Linia 1
Linia 2
Linia 3

Jak długi jest pusty wiersz?
2)

Jakie są wartości ASCII?
13
10

Lub jeśli wolisz podać swój ciąg w jednym wierszu (prawie!), Możesz użyć REPLACE()takiego (opcjonalnie użyć CHAR(13)+CHAR(10)jako zamiennika):

PRINT REPLACE('Line 1`Line 2`Line 3','`','
')
AjV Jsy
źródło
16

Po Google ...

Pobieranie kodu ze strony internetowej:

CREATE TABLE CRLF
    (
        col1 VARCHAR(1000)
    )

INSERT CRLF SELECT 'The quick brown@'
INSERT CRLF SELECT 'fox @jumped'
INSERT CRLF SELECT '@over the '
INSERT CRLF SELECT 'log@'

SELECT col1 FROM CRLF

Returns:

col1
-----------------
The quick brown@
fox @jumped
@over the
log@

(4 row(s) affected)


UPDATE CRLF
SET col1 = REPLACE(col1, '@', CHAR(13))

Wygląda na to, że można to zrobić, zastępując symbol zastępczy znakiem CHAR (13)

Dobre pytanie, nigdy nie zrobiłem tego sam :)

Rob Cooper
źródło
4
Ale jeśli tekst zawiera adres e-mail? „[email protected]” staje się „jon bob.com” (z nową linią w e-sukience)
intrepidis
4
@ChrisNash następnie użyj innego symbolu zastępczego (np. „|”, „~” Lub wielu znaków „! #!”). Zobacz tę odpowiedź poniżej: stackoverflow.com/a/31179/179311 .
bradlis7
1
„CONCAT (CHAR (13), CHAR (10))” („\ r \ n”) byłoby lepsze dla środowiska Windows, co, jak zakładam, jest przypadkiem (SQL Server) cs.toronto.edu/~krueger/csc209h/ tut / line-endings.html
d.popov
12

Dotarłem tutaj, ponieważ martwiłem się, że cr-lfs, które podałem w ciągach C #, nie były pokazywane w odpowiedziach na zapytania SQl Server Management Studio.

Okazuje się, że tam są, ale nie są wyświetlane.

Aby „zobaczyć” cr-lfs, użyj instrukcji print, takiej jak:

declare @tmp varchar(500)    
select @tmp = msgbody from emailssentlog where id=6769;
print @tmp
Bruce Allen
źródło
4

Oto funkcja C #, która wstawia wiersz tekstowy do istniejącego obiektu blob tekstowego, ograniczonego przez CRLF i zwraca wyrażenie T-SQL odpowiednie dla operacji INSERTlub UPDATEoperacji. Ma w sobie część naszej zastrzeżonej obsługi błędów, ale kiedy go rozprujesz, może być pomocny - mam nadzieję, że tak.

/// <summary>
/// Generate a SQL string value expression suitable for INSERT/UPDATE operations that prepends
/// the specified line to an existing block of text, assumed to have \r\n delimiters, and
/// truncate at a maximum length.
/// </summary>
/// <param name="sNewLine">Single text line to be prepended to existing text</param>
/// <param name="sOrigLines">Current text value; assumed to be CRLF-delimited</param>
/// <param name="iMaxLen">Integer field length</param>
/// <returns>String: SQL string expression suitable for INSERT/UPDATE operations.  Empty on error.</returns>
private string PrependCommentLine(string sNewLine, String sOrigLines, int iMaxLen)
{
    String fn = MethodBase.GetCurrentMethod().Name;

    try
    {
        String [] line_array = sOrigLines.Split("\r\n".ToCharArray());
        List<string> orig_lines = new List<string>();
        foreach(String orig_line in line_array) 
        { 
            if (!String.IsNullOrEmpty(orig_line))  
            {  
                orig_lines.Add(orig_line);    
            }
        } // end foreach(original line)

        String final_comments = "'" + sNewLine + "' + CHAR(13) + CHAR(10) ";
        int cum_length = sNewLine.Length + 2;
        foreach(String orig_line in orig_lines)
        {
            String curline = orig_line;
            if (cum_length >= iMaxLen) break;                // stop appending if we're already over
            if ((cum_length+orig_line.Length+2)>=iMaxLen)    // If this one will push us over, truncate and warn:
            {
                Util.HandleAppErr(this, fn, "Truncating comments: " + orig_line);
                curline = orig_line.Substring(0, iMaxLen - (cum_length + 3));
            }
            final_comments += " + '" + curline + "' + CHAR(13) + CHAR(10) \r\n";
            cum_length += orig_line.Length + 2;
        } // end foreach(second pass on original lines)

        return(final_comments);


    } // end main try()
    catch(Exception exc)
    {
        Util.HandleExc(this,fn,exc);
        return("");
    }
}
Carl Niedner
źródło
4

Powiedziałbym

concat('This is line 1.', 0xd0a, 'This is line 2.')

lub

concat(N'This is line 1.', 0xd000a, N'This is line 2.')
Ken Kin
źródło
3

To zawsze jest fajne, ponieważ kiedy dostajesz wyeksportowane listy, powiedzmy Oracle, wtedy dostajesz rekordy obejmujące kilka linii, co z kolei może być interesujące dla, powiedzmy, plików cvs, więc uważaj.

W każdym razie odpowiedź Roba jest dobra, ale radzę użyć czegoś innego niż @, spróbuj jeszcze raz, na przykład §§ @@ §§ lub coś takiego, aby miał szansę na wyjątkowość. (Ale pamiętaj o długości pola varchar/ do nvarcharktórego wstawiasz ...)

neslekkiM
źródło
3

Wszystkie te opcje działają w zależności od sytuacji, ale żadna z nich może nie działać, jeśli używasz SSMS (jak wspomniano w niektórych komentarzach SSMS ukrywa CR / LF)

Więc zamiast jeździć po zakręcie, sprawdź to ustawienie

Tools | Options

który zastąpi

Truby
źródło