line breaks lost in sql server - sql-server

I am entering error information into an ErrorLog table in my database. I have a utility class to do this:
ErrorHandler.Error("Something has broken!!\n\nDescription");
This works fine. However, when I try to access this table, the line breaks no longer seem to be present.
If I SELECT the table:
SELECT * from ErrorLog ORDER BY ErrorDate
there are no line breaks present in the log. This is kind of expected, as line breaks in one-line rows would break the formatting. However, If I copy the data out, the line break characters have been lost, and the data is all on one line.
How do I get line breaks in data at the end of my query when I put line breaks in? I don't know if the string has been stripped of line breaks when it enters the table, or if the viewer in SQL Server Management Studio has stripped out the line breaks.
The data type of the column into which error messages are put is nvarchar(Max), if that makes a difference.
EDIT: Unexpectedly, Pendri's solution didn't work.
Here is an excerpt of the string just before it passes into the SQL server:
POST /ipn/paymentResponse.ashx?installation=272&msgType=result HTTP/1.0\n\rContent-Length: 833\n\rContent-Type:
And here is the same string when I extract it from the grid viewer in SQL Server Management Studio:
POST /ipn/paymentResponse.ashx?installation=272&msgType=result HTTP/1.0 Content-Length: 833 Content-Type:
The place where the line break should be has been double spaced.
Any ideas?

No need to replace string input\output, you need just pick up correct option:
Tools -> Options...
> Query Results
> SQL Server
> Results to Grid
set "Retain CR\LF on copy or save" to true.
And don't forget to restart your management studio!
according Charles Gagnon answer

SSMS replaces linebreaks with spaces in the grid output. If you use Print to print the values (will go to your messages tab) then the carriage returns will be displayed there if they were stored with the data.
Example:
SELECT 'ABC' + CHAR(13) + CHAR(10) + 'DEF'
PRINT 'ABC' + CHAR(13) + CHAR(10) + 'DEF'
The first will display in a single cell in the grid without breaks, the second will print with a break to the messages pane.
A quick and easy way to print the values would be to select into a variable:
DECLARE #x varchar(100);
SELECT #x = 'ABC' + CHAR(13) + CHAR(10) + 'DEF';
PRINT #x;

Update a couple years later.
As described here, one solution to preserve viewing linebreaks in SSMS is to convert the output to XML:
SELECT * FROM (
SELECT * from ErrorLog ORDER BY ErrorDate
) AS [T(x)] FOR XML PATH
Fortunately, if you have SSMS 2012, this is no longer an issue, as line breaks are retained.

I echo David C's answer, except you should use the "TYPE" keyword so that you can click to open the data in a new window.
Note that any unsafe XML characters will not work well with either of our solutions.
Here is a proof of concept:
DECLARE #ErrorLog TABLE (ErrorText varchar(500), ErrorDate datetime);
INSERT INTO #ErrorLog (ErrorText, ErrorDate) VALUES
('This is a long string with a' + CHAR(13) + CHAR(10) + 'line break.', getdate()-1),
('Another long string with' + CHAR(13) + CHAR(10) + '<another!> line break.', getdate()-2);
SELECT
(
SELECT ErrorText AS '*'
FOR XML PATH(''), TYPE
) AS 'ErrorText',
ErrorDate
FROM #ErrorLog
ORDER BY ErrorDate;
I can confirm that the line breaks are preserved when copying out of a grid in SSMS 2012.

try using char(13) + char(10) instead of '\n' in your string (define a constant and concatenate to your sql)

Another simple solution is to click the "results to text" button in SSMS. Its not super clean, but gives you visibility to line breaks with about half a second of work.

For SQL Server 2008, there is no provision to set "Retain CR\LF on copy or save" to true.
For this issue, what I did is that, replace char(13) with "\r" and replace char(10) with "\n" like below.
REPLACE(REPlACE([COLUMN_NAME],char(13), '\r'),CHAR(10),'\n')
And in the code-behind again I've replaced "\r\n" with a break tag.
I worked out in this way as there was no option provided in SQL 2008 as mentioned above. This answer might be an alternative though.
Thanks

Related

SQL Server : display data/column from SELECT statement

I have a table with data that holds a bunch of HTML attributes.
For example: '<HTML><BODY></BODY></HTML>'
I would like to be able to write a SELECT statement that can grab those values, but display them modified.
So instead of displaying
'<HTML><BODY>DATA</BODY></HTML>'
I want to show:
'<HTML>
<BODY>DATA</BODY>
</HTML>'
Essentially, breaking out each one to a new line, based on finding a '>' value, without modifying the data.
I can't seem to find a way to do this. I tried looking into STRING_SPLIT, but I can't get that to apply from the SELECT part.
Any suggestions where I look?
Edit 2/22 - it appears REPLACE gets me further, but when reviewing this more, it may not be possible.
How would SQL know to break out to a new line when the ending HTML tag appears?
It's almost like I need to use a RegEx in here...
REPLACE(TD.DefDetails, '</', CHAR(13) + CHAR(10) + '</') As DefDetails
STRING_SPLIT can split a single column into multiple rows. STRING_SPLIT does require SQL Server Version 2016+. The following snippet does show an example for this scenario.
USE tempdb;
GO
DECLARE #HTMLString AS VARCHAR(100) = '<HTML><BODY></BODY></HTML>';
SELECT *
FROM STRING_SPLIT(#HTMLString,'>');
Actually appears this is done using REPLACE.
REPLACE(Table.DefDetails, '>', '>'+ CHAR(13) + CHAR(10)) As DefDetails
Demo on db<>fiddle
You can achieve it in this way
SELECT REPLACE('<HTML><BODY></BODY></HTML>', '>', '>'+ CHAR(13))
Or if you want to get the value into rows, you can do this way.
Select value + '>'
from STRING_SPLIT('<HTML><BODY></BODY></HTML>', '>')
where value <> ''
Output

Why does SQL Server Management Studio get these syntax errors from copied code

So while testing some code, I discovered odd behavior with code I had pasted in a query window. Below is a simplified example of where I got the code from:
declare #a nvarchar(max) = '';
select #a = 'select ' + cast(n as char(1)) + ';' + char(13) + 'GO' + char(13) from nums where n = 1;
print #a
exec sp_executesql #a
This was executed in a query window in SSMS. It errors, of course, because of that GO delimiter that won't work in dynamic SQL.
However, just so I could confirm the code itself was OK, I copied it into a new query window. To continue the example:
select 1;
GO
select 1
GO
The first statement gives a syntax error, and the second treats the GO as a column alias. Interestingly, this continued to be true if I just typed code directly into that query window. It didn't affect other windows or new ones, just the one I had pasted the PRINT results into.
The last interesting fact about this is that if I compared doing a LEN() on the above example in the "bad" query window versus one that works as expected, the "bad" query is 26 characters long, but the normal one is 31.
I found that backspacing all the characters didn't seem to help, but that if I did a Select All and did a delete that this seemed to fix it. I assume this means it's getting a non-printable character, but if I do a Select All and copy into Notepad++ with a Show All Symbols option, I don't see anything of note.
Does anyone know why SSMS is behaving this way? I'm using version 17.9 (and running against a SQL Server 2014 instance if that matters).
char(13) is Carriage Return (CR).
char(10) is Linefeed (LF).
Windows uses CRLF as a line terminator.
Linux uses LF as a line terminator.
No modern environment uses just CR as a line terminator as your script does. SSMS happens to render CR by inserting vertical space, and this behavior probably is inherited from the underlying Visual Studio codebase.
SSMS's TSQL batch parser, however, doesn't recognize CR as a line terminator, so it doesn't look for the GO symbol following CR. It works with LF or CRLF.

How to Remove Random Line Breaks in Table to XML File in SQL Server

I have a table with 270,000 rows and I wish to export two of the columns into XML.
I use
SELECT
[WordItem] as w, [Definition] as d
FROM
[dbo].[Dictionary]
FOR XML Path('Word')
to create the XML file, but when I "Save As", the file has random line breaks and which splits some of the XML tags.
Is there a way to fix or avoid this? I want to then convert the XML file to JSON and it's proving difficult because of this (Any advice on how to convert easily convert a large XML file to JSON is welcome too!)
In the meanwhile - as long as SQL Server hasn't got native JSON support - you might try it like this:
DECLARE #json VARCHAR(MAX)=
(
SELECT '{\n"root": {\n"Word": [' +
STUFF(
(
SELECT ',\n{\n"w": "' + [WordItem] + '",\n"d": "' + [Definition] + '"\n}'
FROM [dbo].[Dictionary]
FOR XML PATH('')
),1,1,'')
+ '\n]\n}\n}'
);
SELECT REPLACE(#json,'\n',CHAR(13)+CHAR(10));
If the generated string is bigger than 8192 characters you won't be able to see the full string in SSMS. There is a trick:
SELECT REPLACE(#json,'\n',CHAR(13)+CHAR(10))
FOR XML PATH('');
This will put the generated string in an XML viewer. In the query options you must set the DataGrid XML output size to unlimited. This is a way to get almost any size back...
I ran into this too. The inserted line breaks are not random. It just looks it due to the other (intended) line breaks. They don't show up in SQL Managment Studio's "XML Editor", but when you right click and save on the data, SQL Managment Studio inserts a \r\n after 2033 characters (awfully close to 2048). That seems to match what I was getting when just copy-pasting the "row" from the DataGrid into a text file. Setting the DataGrid XML output size from 2Mb to unlimited doesn't seem to fix this. Copy-paste from the "XML Editor" wasn't an option due to the large data size. "Results to text" and "Results to file" didn't help either.
I ended up replacing legitimate line breaks with ¶ and then replacing newlines with empty string, and ¶ back to new lines with regexs later when I actually wanted to use the XML as XML.
So, in sql:
REPLACE(REPLACE([Value], CHAR(10), '¶'), char(13), '')
then in javascript
parseXML = ( new window.DOMParser() ).parseFromString( data.replace(/\r\n/g, "").replace(/¶/g,"\r\n"), "text/xml");
Side note CAST('<![CDATA[' + [Value] + ']]>' AS XML) [Value] seems to remove the CDATA tag, and encode [Value] into xml. I was sorely confused when my CDATA tags disappeared.
I ran into the same issue today.
Try Azure Data Studio it does not have the same limitations as SSMS.
Works like a charm (at least on the built in preview}

SSMS Results to Grid - CRLF not preserved in copy/paste - any better techniques?

When I have a result set in the grid like:
SELECT 'line 1
line 2
line 3'
or
SELECT 'line 1' + CHAR(13) + CHAR(10) + 'line 2' + CHAR(13) + CHAR(10) + 'line 3'
With embedded CRLF, the display in the grid appears to replace them with spaces (I guess so that they will display all the data).
The problem is that if I am code-generating a script, I cannot simply cut and paste this. I have to convert the code to open a cursor and print the relevant columns so that I can copy and paste them from the text results.
Is there any simpler workaround to preserve the CRLF in a copy/paste operation from the results grid?
The reason that the grid is helpful is that I am currently generating a number of scripts for the same object in different columns - a bcp out in one column, an xml format file in another, a table create script in another, etc...
This issue has been fixed in SSMS 16.5 build 13.0.16000.28 with the addition of an option to preserve CR/LF on copy/save (more details) (Connect bug).
Tools > Options
Expand Query Results > SQL Server > Results to Grid
Tick Retain CR/LF on copy or save
Restart SSMS
This will cause CR, LF, and CRLF to be treated as newlines when you copy a cell.
Answering this for myself because I can never remember where this is:
Warning: There's definitely some kind of bug still with this feature.
First of all, I haven't touched the option in months and have recently rebooted.
I had a query with several columns, one of which contained customer feedback (with linefeeds). When I pasted the results into Google Docs / Excel the feedback went into one line (as I wanted).
I then copied the query to another file and ran it again. This time the results contained line breaks!
So either there is a very odd bug, or some secret shortcut that changes the setting for the current window. Interested if anyone else sees this behavior.
it is a hack, but try this:
wrap your result set in a REPLACE (.....,CHAR(13)+CHAR(10),CHAR(182)) to preserve the line breaks, you can then replace them back
SELECT
REPLACE ('line 1' + CHAR(13) + CHAR(10)+ 'line 2' + CHAR(13) + CHAR(10) + 'line 3'
,CHAR(13)+CHAR(10),CHAR(182)
)
OUTPUT:
----------------------
line 1¶line 2¶line 3
(1 row(s) affected)
replace them back in SQL:
select replace('line 1¶line 2¶line 3',CHAR(182),CHAR(13)+CHAR(10))
output:
-------------------
line 1
line 2
line 3
(1 row(s) affected)
or in a good text editor.
One thing you can do is send results to a file, then use an editor capable of watching a file for changes which has superior capabilities for understanding the output.

SQL Server truncation and 8192 limitation

In SQL Server 2005 I am trying to query a varchar(MAX) column which has some rows with text data that exceed the 8192. Yet, In Management Studio I have under Tools --> Options --> Query Results --> Results to Text --> Max numbers of characters displayed in each column = 8192, which is a maximum. Accordingly, it seems the truncation on these rows occurs only due to the limitation imposed by text output.
The only thing I see to get around this is to use a SUBSTRING function to grab say the first 8000 chars, then the next 8000 chars etc. etc. But this is ugly and error prone.
I should mention that SSIS and BCP are not options for me.
Does anyone have a better suggestion? Thanks!
You can export the data to a flat file which will not be truncated. To do this:
Right click the Database
Click Tasks -> Export Data
Select your Data Source (defaults should be fine)
Choose "Flat File Destination" for the Destination type.
Pick a file name for the output.
On the "Specify Table Copy or Query", choose "Write a query to specify the data to transfer"
Paste in your query
Remaining steps should be self explanatory. This will output the file to text and you can open it in your favorite text editor.
I also use XML but a slightly different method that gets around most of the issues with XML entitisation.
declare #VeryLongText nvarchar(max) = '';
SELECT top 100 #VeryLongText = #VeryLongText + '
' + OBJECT_DEFINITION(object_id)
FROM sys.all_objects
WHERE type='P' and is_ms_shipped=1
SELECT LEN(#VeryLongText)
SELECT #VeryLongText AS [processing-instruction(x)] FOR XML PATH('')
PRINT #VeryLongText /*WILL be truncated*/
Make sure that the "XML data" limit in SSMS is set sufficiently high!
Did you try this simple solution? Only 2 clicks away!
At the query window,
set query options to "Results to Grid", run your query
Right click on the results tab at the grid corner, save results as any files
You will get all the text you want to see in the file!!! I can see 130,556 characters for my result of a varchar(MAX) field
My solution was a bit round-about but got me there (as long as the output is less than 65535 characters):
In SQL Management Studio, set the limit for grid results to 65535 (Tools > Options > Query Results > SQL Server > Results to Grid > Non XML data)
Run the query, output to grid
Right-click the results, choose "Save Results As..." and save the results to a file
Open the file in notepad or similar to get the output
UPDATE: To demonstrate that this works, here's some SQL that selects a single 100,000 character column. If I save the grid output to a csv file, all 100,000 characters are there with no truncation.
DECLARE #test nvarchar(MAX), #i int, #line nvarchar(100)
SET #test = ''; SET #i = 100
WHILE #i < 100000
BEGIN
SET #test = #test + STUFF(REPLICATE('_', 98) + CHAR(13) + CHAR(10), 1, LEN(CAST(#i AS nvarchar)), CAST(#i AS nvarchar))
SET #i = #i + 100
END
SELECT #test
Notes:
It doesn't seem to make any difference what the character length setting is, as I orignally thought.
I'm using SQL 2008 R2 (both the server and Management Studio)
It doesn't seem to make a difference if the long column is stored in a local variable (as in this example), or selected from an actual table
I ran in to this trying to export XML. This is the solution I used:
Select the Result to Grid option, right click the link that shows up in the Results pane, then select Save Results As, choose the All Files file type, give the file a name and click Save. All the xml data is saved correctly to a file.
I'm using SSMS 10, and I could't get Torre's solution to work. The export wizard kept thinking the input column was an image:
The data type for "input column "XML_F52E2B61-18A1-11d1-B105-00805F49916B" (26)" is DT_IMAGE
In SSMS if you select data from a row it is limited to a small number of characters, but if you Edit data from a row, the full value will be there. It might not always be there but if you ctrl-a, ctrl-c then past it in an editor it will all be there.
If given a choice I would have the query return the data as "For XML Auto" or "For XML Raw" or "For XML explicit" that way the limitations are much higher and you can do much more with the outputed results.
I usually use XML to get huge debug string as output (using test harness from Luke):
declare #test nvarchar(max), #i int, #line nvarchar(100)
set #test = ''; set #i = 100
while #i < 100000
begin
set #test = #test + stuff(replicate('_', 98) + char(13) + char(10), 1, len(cast(#i as nvarchar)), cast(#i as nvarchar))
set #i = #i + 100
end
-- ctrl+d for "results to grid" then click the xml output
--select cast('<root>' + #test + '</root>' as xml)
-- revised
select #test for xml path(''), type;
Another workaround , use HeidiSql for this tricky queries. It does not have the limits in the field lenght.
The truncation you are talking about only happens in Management Studio. If you pull the column into another app, it will not be truncated.
There's no way you're using Query Analyzer to talk to SQL Server 2005. Do you mean Management Studio?

Resources