Reputation: 7012
We have TestPartner database in SQL Server. The descriptions of the bugs are stored in "image" datatype column. We need to write a query to display the data as html table. We have this query that reads the data from the respective tables to display the information as xml using For XML
. But converting image datatype to varchar throws an exception: "FOR XML could not serialize the data for node 'TD' because it contains a character (0x0002) which is not allowed in XML. To retrieve this data using FOR XML, convert it to binary, varbinary or image data type and use the BINARY BASE64 directive.".
Query:
DECLARE @ResultsTable nvarchar(MAX)
--Create the XML table with the query results
SET @ResultsTable =
N'<H3>QA Automation Tests Results Summary </H3>' +
N'<table border="1">' +
N'<tr><th>Test Name</th><th>Execution Date</th>' +
N'<th>Check Name</th><th>Description</th></tr>' +
CAST ( (
select distinct Name as TD, '',
(Select CAST(CONVERT(nchar(100),CAST( TPCommandDetail AS BINARY(100) )) as VARCHAR(100)) ) as TD, ''
FROM TestPartnerDB.TP_RESULTS_RECORDS
FOR XML PATH('tr'), TYPE
) AS nvarchar(max) ) + N'</table>'
SELECT @ResultsTable
Surprisingly it works for some records and as soon as you bump the size to say 200. It throws error again. I also tried:
Select CONVERT(varchar(1000), convert(varbinary(1000), tpcommanddetail)) From TestPartnerDB.TP_RESULTS_RECORDS
This returns weird characters for each row. Does anyone know how to get this thing to work?
Upvotes: 26
Views: 121846
Reputation: 440
This is what worked for me.
select cast(cast(imageVal as varbinary(max)) as varchar(max)) from table
Upvotes: 0
Reputation: 2832
What worked for me to convert IMAGE column is:
SELECT convert(varchar(max), cast(mypicture as varbinary(max)), 1)
FROM MyTable
Upvotes: 0
Reputation: 17131
Try this code:
Select MASTER.dbo.Fn_varbintohexstr(tpcommanddetail) From TestPartnerDB.TP_RESULTS_RECORDS
Upvotes: 4
Reputation: 5895
The simple answer is
select cast(cast(my_column as varbinary(max)) as varchar(max)) as column_name
from my_table
This converts the column to varchar format. nvarchar(max) might be better if you have unicode data.
Upvotes: 33
Reputation: 6962
You can convert also like this
convert (varchar(max) , convert (varbinary (max) , blob_data)), cast(cast(blob_data as binary) as varchar(max))
Upvotes: 8
Reputation: 3938
If the data has been stored in the image field as Unicode data, it won't work if you replace the line Select CONVERT(nvarchar(1000), convert(varbinary(1000), tpcommanddetail)) From TestPartnerDB.TP_RESULTS_RECORDS
with Select CONVERT(varchar(1000), convert(varbinary(1000), tpcommanddetail)) From TestPartnerDB.TP_RESULTS_RECORDS
.
It's very important that the first conversion from binary data to text be made with the right collation and size of characters: if the text is in Ascii, you must use varchar() and if the text is in Unicode, you must use nvarchar().
The second conversion from nvarchar(100) to varchar(100) looks useless to me.
The use of binary(100) instead of varbinary(100) looks also very suspicious to me.
Finally, if you get strange characters like 0x0002 then maybe this is why that this has been stored in an image field instead of a text field: this is a specially formated field where not all characters are text characters. However, as you didn't show us the result of printing the original field in binary (or more exactly, in hexadecimal) or of any of your results, it's impossible to say anything more.
I've just cooked up a few tests; with these, you should be able to understand what's happening:
select ascii ('A'), unicode(N'A');
select convert (binary(2), ascii('A')), convert (binary(2), unicode(N'A'));
--
declare @ab binary(10), @vab varbinary(10);
declare @nab binary(10), @vnab varbinary(10);
--
set @ab = convert (binary (10), 'AB');
set @vab = convert (varbinary (10), 'AB');
set @nab = convert (binary (10), N'AB');
set @vnab = convert (varbinary (10), N'AB');
--
select @ab, @vab, @nab, @vnab;
--
select convert(varchar(10), @ab) + '*',
convert(varchar(10), @vab) + '*',
convert(varchar(10), @nab) + '*',
convert(varchar(10), @vnab) + '*';
--
select len(convert(varchar(10), @ab)),
len(convert(varchar(10), @vab)),
len(convert(varchar(10), @nab)),
len(convert(varchar(10), @vnab));
--
select len(convert(varchar(10), @ab) + '*'),
len(convert(varchar(10), @vab) + '*'),
len(convert(varchar(10), @nab) + '*'),
len(convert(varchar(10), @vnab) + '*');
--
select convert(nvarchar(10), @ab) + '*',
convert(nvarchar(10), @vab) + '*',
convert(nvarchar(10), @nab) + '*',
convert(nvarchar(10), @vnab) + '*';
--
select len(convert(nvarchar(10), @ab)),
len(convert(nvarchar(10), @vab)),
len(convert(nvarchar(10), @nab)),
len(convert(nvarchar(10), @vnab));
--
select convert(varchar(10), convert(nvarchar(10), @ab)) + '*',
convert(varchar(10), convert(nvarchar(10), @vab)) + '*',
convert(varchar(10), convert(nvarchar(10), @nab)) + '*',
convert(varchar(10), convert(nvarchar(10), @vnab)) + '*';
--
select len(convert(varchar(10), convert(nvarchar(10), @ab))),
len(convert(varchar(10), convert(nvarchar(10), @vab))),
len(convert(varchar(10), convert(nvarchar(10), @nab))),
len(convert(varchar(10), convert(nvarchar(10), @vnab)));
--
select convert(nvarchar(10), @nab) for xml path('tr');
select convert(varchar(10), convert(nvarchar(10), @nab)) for xml path('tr');
select 'The Name' as td, '', convert(nvarchar(10), @nab) as td for xml path('tr');
Upvotes: 4
Reputation: 2404
My guess would be that the data stored in your image column is not 'normal' text - I would guess that it's some arbitrary data structure (hence the decision to use image rather than varchar) ?
I tried this without a problem:
declare @data varchar(max)
declare @fred table (d1 varchar(max), d2 xml, d3 image)
set @data = 'here is some data'
while (len(@data) < 200) set @data = @data + ' ' + cast(rand() as varchar)
insert into @fred (d1,d2,d3) values (@data,@data,@data)
set @data = 'here is some more data'
while (len(@data) < 200) set @data = @data + ' ' + cast(rand() as varchar)
insert into @fred (d1,d2,d3) values (@data,@data,@data)
declare @xml xml
set @xml = (select cast(cast(d3 as varbinary(max)) as varchar(max)) as 'td' from @fred FOR XML PATH('tr'), TYPE)
select @xml
Upvotes: 2