【问题标题】:Convert image datatype into varchar in sql server 2008在 sql server 2008 中将图像数据类型转换为 varchar
【发布时间】:2011-10-24 18:32:24
【问题描述】:

我们在 SQL Server 中有 TestPartner 数据库。错误的描述存储在“图像”数据类型列中。我们需要编写一个查询以将数据显示为 html 表。我们有这个查询,它从各个表中读取数据,以使用For XML 将信息显示为 xml。但是将图像数据类型转换为 varchar 会引发异常:“FOR XML 无法序列化节点 'TD' 的数据,因为它包含 XML 中不允许的字符 (0x0002)。要使用 FOR XML 检索此数据,请将其转换为二进制, varbinary 或 image 数据类型并使用 BINARY BASE64 指令。”。

查询:

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

令人惊讶的是,它适用于某些记录,一旦您将大小增加到 200,它就会再次引发错误。我也试过了:

Select CONVERT(varchar(1000), convert(varbinary(1000), tpcommanddetail)) From TestPartnerDB.TP_RESULTS_RECORDS

这会为每一行返回奇怪的字符。有谁知道如何让这个东西工作?

【问题讨论】:

  • 这必须是一个大的 WTF 才能将文本数据存储在二进制字段中 - 祝你好运......

标签: sql sql-server-2008


【解决方案1】:

简单的答案是

select cast(cast(my_column as varbinary(max)) as varchar(max)) as column_name
from   my_table

这会将列转换为 varchar 格式。如果您有 unicode 数据,nvarchar(max) 可能会更好。

【讨论】:

    【解决方案2】:

    你也可以这样转换

    convert (varchar(max) , convert (varbinary (max) , blob_data)), cast(cast(blob_data as binary) as varchar(max)) 
    

    【讨论】:

    • 此解决方案有效,但它截断了结果字符串。我最终使用了SELECT CONVERT(xml, CONVERT(varbinary(MAX), Fields))
    【解决方案3】:

    试试这个代码:

    Select  MASTER.dbo.Fn_varbintohexstr(tpcommanddetail) From TestPartnerDB.TP_RESULTS_RECORDS
    

    【讨论】:

      【解决方案4】:

      如果数据已经作为 Unicode 数据存储在图像字段中,如果将行 Select CONVERT(nvarchar(1000), convert(varbinary(1000), tpcommanddetail)) From TestPartnerDB.TP_RESULTS_RECORDS 替换为 Select CONVERT(varchar(1000), convert(varbinary(1000), tpcommanddetail)) From TestPartnerDB.TP_RESULTS_RECORDS 将不起作用。

      从二进制数据到文本的第一次转换必须使用正确的排序规则和字符大小:如果文本是 Ascii,则必须使用 varchar(),如果文本是 Unicode,则必须使用nvarchar()。

      从 nvarchar(100) 到 varchar(100) 的第二次转换在我看来毫无用处。

      使用 binary(100) 代替 varbinary(100) 在我看来也很可疑。

      最后,如果你得到像 0x0002 这样的奇怪字符,那么也许这就是为什么它被存储在图像字段而不是文本字段中的原因:这是一个特殊格式的字段,其中并非所有字符都是文本字符。但是,由于您没有向我们展示以二进制(或更准确地说,以十六进制)或任何结果打印原始字段的结果,因此无法再说什么。

      我刚刚做了一些测试;有了这些,你应该能够理解发生了什么:

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

      【讨论】:

        【解决方案5】:

        我的猜测是存储在您的图像列中的数据不是“正常”文本 - 我猜它是一些任意数据结构 (因此决定使用图像而不是 varchar)

        我试过没有问题:

            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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-12
          • 1970-01-01
          • 1970-01-01
          • 2011-11-30
          • 2015-05-10
          • 1970-01-01
          • 2010-10-15
          • 2023-03-06
          相关资源
          最近更新 更多