sql-server - 在 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)
解决方案
问题是您的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 和varchar
27。由于varchar
具有更高的优先级,varchar
因此返回 a ,并且从表达式返回的任何值CONVERT(varbinary(MAX), T.N.value('DocContent[1]', 'varchar(max)'))
都将隐式转换为 a varchar(MAX)
。
一个CASE
表达式不能返回不同的数据类型(如上,如果WHEN
/在同一表达式中返回与/ELSE
不同的数据类型,具有较低的优先级,它将被隐式转换),但是,也许你在这之后?WHEN
ELSE
CASE
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 NULL
or NOT NULL
,因此这些表达式之一不可能不为真。此外,由于工作方式ISNULL
(它返回第一个参数的数据类型,它不使用数据类型优先级),您不需要显式地CONVERT
显示后面的值:
ISNULL(CONVERT(varbinary(MAX),T.N.value('DocContent[1]', 'varchar(max)')),'')
推荐阅读
- redirect - CNAME 也会重定向子文件夹吗?
- git - 为什么 powershell env 可以在本地工作,但不能与 dockerfile 一起工作?
- kubernetes - 如何在 GKE 中添加与 Internet 不同的默认路由并使集群仍然工作?
- html - 为什么这些 HTML 列标题未对齐?
- r - 用于对重叠集的结果求和的 R 数据透视表?
- postgresql - 如何在 typeorm 中使用 postgres `array_agg`?
- java - 从 JSONObject 获取“id”的最短方法
- python - 替换值并获取“SettingWithCopyWarning:试图在 DataFrame 中的切片副本上设置值”
- ansible - 人们通常如何处理记录直到循环而不在控制台/或 ansible 主日志上生成太多日志记录?
- java - UnknownHostException:从 Jedis 切换到 Redisson 后 6 次查询后无法解析“my-redis-host”