【问题标题】:Unable to convert varchar to binary in case statement在 case 语句中无法将 varchar 转换为二进制
【发布时间】:2019-11-21 09:54:16
【问题描述】:

在 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-server type-conversion


【解决方案1】:

问题在于您的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 表达式,返回数据类型是具有最高优先级 Data type precedence (Transact-SQL) 的任何数据类型。 varbinary 的优先级为 29,varchar 的优先级为 27。由于 varchar 的优先级更高,因此会返回 varchar,而从表达式 CONVERT(varbinary(MAX), T.N.value('DocContent[1]', 'varchar(max)')) 返回的任何值都将隐式 转换为varchar(MAX)

CASE 表达式不能返回不同的数据类型(如上,如果 WHEN/ELSE 在相同的 CASE 表达式中返回的数据类型不同于 WHEN/ELSE优先级它会被隐式转换),但是,也许你在这之后?

   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 NULLNOT NULL,因此这些表达式之一不可能不正确。此外,由于ISNULL 的工作方式(它返回第一个参数的数据类型,它不使用数据类型优先级),您不需要显式地CONVERT 后面的值: p>

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-11
    • 2022-07-23
    • 2022-01-01
    • 1970-01-01
    • 2020-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多