676

I didn't see any similar questions asked on this topic, and I had to research this for something I'm working on right now. Thought I would post the answer for it in case anyone else had the same question.

Csharp
  • 2,916
  • 16
  • 50
  • 77
Mark Struzinski
  • 32,945
  • 35
  • 107
  • 137
  • 10
    To test your output, if using SSMS make sure the option Retain CR/LF on copy or save is checked, else all pasted results will loose the line feed. You find this at settings, query results, sql server, results to grid. – Stefanos Zilellis Nov 09 '18 at 10:19
  • 1
    @StefanosZilellis and make sure to open a new query window for the setting changes to take effect. – Don Cheadle May 16 '19 at 20:09

11 Answers11

718

char(13) is CR. For DOS-/Windows-style CRLF linebreaks, you want char(13)+char(10), like:

'This is line 1.' + CHAR(13)+CHAR(10) + 'This is line 2.'
Sören Kuklau
  • 19,454
  • 7
  • 52
  • 86
  • 37
    char(13)+char(10) didn't work for me in windows. I just used char(10) – nima Jun 11 '11 at 07:52
  • 8
    @Nima: Some applications will use one or the other or both to show a new line, however many applications you may output this text to will require both do appear in succession to signify a new line. I find it safe to use both. You can list here which of your apps it doesn't work for. I prefer the CHAR(0x0D) + CHAR(0x0A) hexadecimal values myself, but to each their own. – MikeTeeVee Mar 27 '13 at 07:02
  • 2
    I used this method successfully, but ran into a problem with it: once you have more than about 480 `+`, SQL Server will start complaining that your query is too deeply nested. My solution was instead to use Rob Cooper's answer instead, but with a much longer and more obscure token. – Marcus Downing Apr 21 '15 at 11:40
  • It worked but I had to put it twice: 'This is line 1.' + CHAR(13)+CHAR(10) + CHAR(13)+CHAR(10) + 'This is line 2.' – starplush Jun 10 '15 at 18:16
  • 8
    Providing \r\n would mean acknowledgement that regular expressions exist and that there are users capable of understanding and using them. – wwmbes Jun 30 '16 at 08:30
  • 10
    @HBlackorby \r and \n predate Java-anything by decades with their use in C; and are standard in Python, PHP, Ruby, C++, C#, etc... – Uueerdo Oct 18 '17 at 23:29
  • 1
    For anyone on SSMS v16.5 or higher (e.g. v18.5) wondering why this doesn't copy out correctly, go _Tools > Options > Query Results > SQL Server > Results to Grid > Retain CR/LF on copy or save_, (change effective after you close & reopen query window). `Ctrl + Q` with _Results to Grid_ will also get you there faster. – Simon C Jun 26 '20 at 09:41
338

I found the answer here: http://blog.sqlauthority.com/2007/08/22/sql-server-t-sql-script-to-insert-carriage-return-and-new-line-feed-in-code/

You just concatenate the string and insert a CHAR(13) where you want your line break.

Example:

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

This prints out the following:

This is line 1.
This is line 2.

Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
Mark Struzinski
  • 32,945
  • 35
  • 107
  • 137
  • 1
    But how do you do it programatically? Let's say from c#? – Daniel Dolz Nov 12 '12 at 13:34
  • 20
    It seems you need use PRINT @text rather SELECT to get this result. – QMaster Mar 25 '14 at 13:51
  • 3
    BTW: You can also use `NCHAR(0x1234)` to get a unicode character. Not necessary for inserting line breaks, but can come in handy if one must insert/search for unicode characters. – Paul Groke Oct 02 '14 at 12:33
  • 3
    In SQL Server 2016, I only see it print the two lines if I use `print` instead of `select`, such as: `DECLARE @text NVARCHAR(100); SET @text = 'This is line 1.' + CHAR(13) + 'This is line 2.'; print @text;` – devinbost Jan 19 '17 at 19:10
  • 1
    @devinbost that's because SSMS result grids [hide line breaks by default](https://stackoverflow.com/questions/2679481) – Michel de Ruiter Apr 05 '18 at 14:24
  • 15
    To test your output, if using SSMS make sure the option Retain CR/LF on copy or save is checked, else all pasted results will loose the line feed. You find this at settings, query results, sql server, results to grid. – Don Cheadle May 16 '19 at 20:18
  • 4
    What @DonCheadle said, AND you may have to close the query tab and re-open it for that setting to take effect. ;) – James Wilkins Mar 18 '20 at 23:30
102

Another way to do this is as such:

INSERT CRLF SELECT 'fox 
jumped'

That is, simply inserting a line break in your query while writing it will add the like break to the database. This works in SQL server Management studio and Query Analyzer. I believe this will also work in C# if you use the @ sign on strings.

string str = @"INSERT CRLF SELECT 'fox 
    jumped'"
Frank V
  • 25,141
  • 34
  • 106
  • 144
  • 17
    In other words, the syntax of the SQL language simply allows raw line feeds in strings literals. It works this way in all engines I've tried (SQL Server, Oracle, MySQL, PostgreSQL and SQLite). – Álvaro González Feb 13 '14 at 15:32
  • sometimes this randomly quits working if you use it in stored procedures – DaFi4 Nov 20 '19 at 12:20
51

All of these options work depending on your situation, but you may not see any of them work if you're using SSMS (as mentioned in some comments SSMS hides CR/LFs)

So rather than driving yourself round the bend, Check this setting in

Tools | Options

which will replace the

Trubs
  • 2,829
  • 1
  • 24
  • 33
  • 7
    I'm on v18.2 of SSMS and I had trouble getting this setting to stick. I had to check it on, then exit SSMS and restart. And make sure you only have 1 instance of SSMS running. The second instance will overwrite the setting w/ the original value. But eventually I was successful. +1 – Jay Cummins Jul 21 '20 at 13:42
  • 3
    Also note, If you output to Text instead of to Grid then the CR/LF will be preserved as expected without having to make any changes to the application options. – Code Ranger Sep 30 '21 at 09:52
  • 1
    requires restart of SSMS to take this change effect. – PAS Aug 05 '22 at 22:15
36

Run this in SSMS, it shows how line breaks in the SQL itself become part of string values that span lines :

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

Result :
Line 1
Line 2
Line 3

How long is a blank line feed?
2

What are the ASCII values?
13
10

Or if you'd rather specify your string on one line (almost!) you could employ REPLACE() like this (optionally use CHAR(13)+CHAR(10) as the replacement) :

PRINT REPLACE('Line 1`Line 2`Line 3','`','
')
AjV Jsy
  • 5,799
  • 4
  • 34
  • 30
18

Following a Google...

Taking the code from the website:

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

Looks like it can be done by replacing a placeholder with CHAR(13)

Good question, never done it myself :)

Rob Cooper
  • 28,567
  • 26
  • 103
  • 142
  • 4
    But if the text has an email address in it? "jon@bob.com" becomes "jon bob.com" (with a newline in the e-dress) – intrepidis Jan 16 '15 at 15:52
  • 4
    @ChrisNash then use a different placeholder (e.g. "|", "~", or multiple characters, "!#!"). See this answer below: http://stackoverflow.com/a/31179/179311. – bradlis7 Mar 25 '15 at 19:29
  • 1
    "CONCAT (CHAR(13) , CHAR(10))" ("\r\n") would be better for windows environment, which I assume is the case (SQL Server) http://www.cs.toronto.edu/~krueger/csc209h/tut/line-endings.html – d.popov Mar 29 '16 at 07:39
  • This is non-deterministic. A table is defined as an *unordered* set of records. There is no guarantee that the database engine will return the records in the order inserted. Without a second column to preserve the order in some way (a simple `IDENTITY()` would work) and an `ORDER BY` in your output query, the server will return the records in whichever order it finds convenient. That *may* be the same order they were inserted, but the server is allowed to do it however it wants to without an `ORDER BY`. – Bacon Bits Sep 23 '20 at 12:25
13

I got here because I was concerned that cr-lfs that I specified in C# strings were not being shown in SQl Server Management Studio query responses.

It turns out, they are there, but are not being displayed.

To "see" the cr-lfs, use the print statement like:

declare @tmp varchar(500)    
select @tmp = msgbody from emailssentlog where id=6769;
print @tmp
OnaBai
  • 40,767
  • 6
  • 96
  • 125
Bruce Allen
  • 191
  • 2
  • 7
10

I'd say

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

or

concat(N'This is line 1.', 0xd000a, N'This is line 2.')
Ken Kin
  • 4,503
  • 3
  • 38
  • 76
5

Here's a C# function that prepends a text line to an existing text blob, delimited by CRLFs, and returns a T-SQL expression suitable for INSERT or UPDATE operations. It's got some of our proprietary error handling in it, but once you rip that out, it may be helpful -- I hope so.

/// <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("");
    }
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Carl Niedner
  • 173
  • 2
  • 9
3

This is always cool, because when you get exported lists from, say Oracle, then you get records spanning several lines, which in turn can be interesting for, say, cvs files, so beware.

Anyhow, Rob's answer is good, but I would advise using something else than @, try a few more, like §§@@§§ or something, so it will have a chance for some uniqueness. (But still, remember the length of the varchar/nvarchar field you are inserting into..)

Andrew Steitz
  • 1,856
  • 15
  • 29
neslekkiM
  • 693
  • 1
  • 8
  • 19
1

In some special cases you may find this useful (e.g. rendering cell-content in MS Report )
example:

select * from 
(
values
    ('use STAGING'),
    ('go'),
    ('EXEC sp_MSforeachtable 
@command1=''select ''''?'''' as tablename,count(1) as anzahl from  ? having count(1) = 0''')
) as t([Copy_and_execute_this_statement])
go
cjonas
  • 71
  • 1
  • 4
  • Can you add some more explanation, I have no idea how this works or how to use it – reggaeguitar Sep 24 '20 at 19:11
  • 1
    this statement delivers not a string with CR\LF in it, but a little table with one column ( named [Copy_and_execute_this_statement] ) and three rows. This is perhaps suitable for consumers, which swallow CR\LF but can consume tables ( e.g. MS Report ) another simple example would be " select * from ( values ( 'Adam'),('Eva')) as t([some_name])" – cjonas Sep 26 '20 at 16:47