views:

339

answers:

4

In this live SQL Server 2008 (build 10.0.1600) database, there's an Events table, which contains a text column named Details. (Yes, I realize this should actually be a varchar(MAX) column, but whoever set this database up did not do it that way.)

This column contains very large logs of exceptions and associated JSON data that I'm trying to access through SQL Server Management Studio, but whenever I copy the results from the grid to a text editor, it truncates it at 43679 characters.

I've read on various locations on the Internet that you can set your Maximum Characters Retrieved for XML Data in Tools > Options > Query Results > SQL Server > Results To Grid to Unlimited, and then perform a query such as this:

select Convert(xml, Details) from Events
where EventID = 13920

(Note that the data is column is not XML at all. CONVERTing the column to XML is merely a workaround I found from Googling that someone else has used to get around the limit SSMS has from retrieving data from a text or varchar(MAX) column.)

However, after setting the option above, running the query, and clicking on the link in the result, I still get the following error:

Unable to show XML. The following error happened: Unexpected end of file has occurred. Line 5, position 220160.

One solution is to increase the number of characters retrieved from the server for XML data. To change this setting, on the Tools menu, click Options.

So, any idea on how to access this data? Would converting the column to varchar(MAX) fix my woes?

A: 

It sounds like the Xml may not be well formed. If that is the case, then you will not be able to cast it as Xml and given that, you are limited in how much text you can return in Management Studio. However, you could break up the text into smaller chunks like so:

With Tally As
    (
        Select ROW_NUMBER() OVER ( ORDER BY s1.object_id ) - 1 As Num
        From sys.sysobjects As s1
            Cross Join sys.sysobjects As s2
    )
Select Substring(T1.textCol, T2.Num * 8000 + 1, 8000)
From Table As T1
    Cross Join Tally As T2
Where T2.Num <= Ceiling(Len(T1.textCol) / 8000)
Order By T2.Num

You would then need to manually combine them again.

EDIT

It sounds like there are some characters in the text data that the Xml parser does not like. You could try converting those values to entities and then try the Convert(xml, data) trick. So something like:

Update Table
Set Data = Replace(Cast(Data As varchar(max)),'<','&lt;')

(I needed to cast to varchar(max) because the replace function will not work on text columns. There should not be any reason you couldn't convert those text columns to varchar(max).)

Thomas
Oh, I suppose I should mention that the column is not XML at all. CONVERTing the column to XML is merely a workaround I found from Googling that someone else has used to get around the limit SSMS has from retrieving data from a `text` or `varchar(MAX)` column.
adamjford
A: 

The data type TEXT is old and should not be used anymore, it is a pain to select data out of a TEXT column.

ntext, text, and image (Transact-SQL)

ntext, text, and image data types will be removed in a future version of Microsoft SQL Server. Avoid using these data types in new development work, and plan to modify applications that currently use them. Use nvarchar(max), varchar(max), and varbinary(max) instead.

you need to use TEXTPTR (Transact-SQL) to retrieve the text data.

Also see this article on Handling The Text Data Type.

KM
Will converting the column to `varchar(MAX)` prevent SSMS from truncating the data from it?
adamjford
I would first use SSMS to generate the scrip to convert your TEXT column to varchar(max). From there you could evaluate if you want to further convert it to an XML column. As for SSMS display limits, results to grid can be set to display up to 65,535 chars of non xml data per column, and up to an unlimited amount of xml data (fyi, table columns of XML type can only store 2 GB). While results to text is limited to 8192 chars per column. To set these default max limits, just go to (in SSMS) TOOLS menu, then OPTIONS... then QUERY RESULTS, then SQL SERVER, then RESULTS TO GRID or RESULTS TO TEXT.
KM
A: 

You are out of luck, I think. THe problem is not a SQL level problem as all other answers seem to focus on, but simply one of the user interface. Management Studio is not meant to be a general purpose / generic data access interface. It is not there to be your interface, but your administrative area, and it has serious limitations handling binary data and large test data - because people using it within the specified usage profile will not run into this problem.

Presenting large text data is simply not the planned usage.

Your only choice would be a table valued function that takes the text input and cuts it rows for every line, so that Management Studio gets a list of rows, not a single row.

TomTom
+1  A: 

Updated Answer I've recently come across a better way of doing this that avoids issues of SQL Server converting < to &lt; etc.

Example code below

DECLARE @S varchar(max)

SELECT @S = ''

SELECT @S = @S + '
' + OBJECT_DEFINITION(OBJECT_ID) FROM SYS.PROCEDURES

SELECT @S AS [processing-instruction(x)] FOR XML PATH('')

I think the original source is Adam Machanic here https://connect.microsoft.com/SQLServer/feedback/details/499618/ssms-allow-large-text-to-be-displayed-in-as-a-link

Original Answer If you have SSMS tools http://www.ssmstoolspack.com/ installed one of it's facilities is a script table facility that includes the full text of long fields. You can limit it to particular rows.

Is it not possible though that it is whingeing because the data is not valid XML and something like the following might work?

convert(xml,'<xml><![CDATA[' + cast(details as varchar(max)) + ']]></xml>')
Martin Smith
Adding CDATA to the Convert statement worked! Thanks a lot. :)
adamjford