首页 > 解决方案 > 在 case 语句中无法将 varchar 转换为二进制

问题描述

在 case 语句中无法将 varchar 转换为二进制。我曾经从 xml 读取数据并尝试在数据不为空时进行转换。

下面是示例代码

 Declare @docs varchar(max)=N'<root>
                            <Documents>
                                <Document>
                                    <DocId>1</DocId>
                                    <DocName>DocA</DocName>
                                    <DocContent>ABCDEFG</DocContent>
                                </Document>
                                <Document>
                                    <DocId>2</DocId>
                                    <DocName>DocB</DocName>
                                    <DocContent>ABCDEFG</DocContent>
                                </Document>
                                <Document>
                                    <DocId>3</DocId>
                                    <DocName>DocC</DocName>
                                    <DocContent>ABCDEFG</DocContent>
                                </Document>
                            </Documents>
                        </root>'
 Declare @xmlDoc XML=Convert(XML,@docs)
 select T.N.value('DocId[1]', 'int') AS 'DocId',
 T.N.value('DocName[1]', 'varchar(max)') AS 'DocName',
 CONVERT(VARBINARY(max),T.N.value('DocContent[1]', 'varchar(max)')) as 'Convering',
 CASE 
   WHEN T.N.value('DocContent[1]', 'varchar(max)') IS NOT NULL THEN 
   CONVERT(VARBINARY(max),T.N.value('DocContent[1]', 'varchar(max)')) 
   WHEN T.N.value('DocContent[1]', 'varchar(max)') IS NULL THEN ''
   ELSE T.N.value('DocContent[1]', 'varchar(max)')
 END 
 AS 'Not Converting'
 FROM @xmlDoc.nodes('/root/Documents/Document') AS T(N)

在此处输入图像描述

标签: sql-servertype-conversion

解决方案


问题是您的CASE 表达式及其返回值。在表达式中,您有 3 个可以返回的值(我已将它们的数据类型添加到其中):

CONVERT(varbinary(MAX), T.N.value('DocContent[1]', 'varchar(max)')) --varbinary(MAX)
'' --varchar(1)
T.N.value('DocContent[1]', 'varchar(max)') --varchar(MAX)

对于CASE表达式,返回数据类型是具有最高优先级 数据类型优先级 (Transact-SQL)的数据类型。varbinary优先级分别为 29 和varchar27。由于varchar具有更高的优先级,varchar因此返回 a ,并且从表达式返回的任何值CONVERT(varbinary(MAX), T.N.value('DocContent[1]', 'varchar(max)'))都将隐式转换为 a varchar(MAX)

一个CASE表达式不能返回不同的数据类型(如上,如果WHEN/在同一表达式中返回与/ELSE不同的数据类型,具有较低的优先级,它将被隐式转换),但是,也许你在这之后?WHENELSECASE

   CONVERT(varbinary(MAX),CASE
                               WHEN T.N.value('DocContent[1]', 'varchar(max)') IS NOT NULL THEN T.N.value('DocContent[1]', 'varchar(max)')
                               WHEN T.N.value('DocContent[1]', 'varchar(max)') IS NULL THEN ''
                               ELSE T.N.value('DocContent[1]', 'varchar(max)')
                          END) AS [will Convert]

编辑:正如@gotqn 所指出的,以上内容仍然可以缩短。首先,这里不需要ELSE,因为您可以检查是否相同的表达式IS NULLor NOT NULL,因此这些表达式之一不可能不为真。此外,由于工作方式ISNULL(它返回第一个参数的数据类型,它不使用数据类型优先级),您不需要显式地CONVERT显示后面的值:

ISNULL(CONVERT(varbinary(MAX),T.N.value('DocContent[1]', 'varchar(max)')),'')

推荐阅读