Невозможно преобразовать varchar в двоичный файл в операторе case - PullRequest
0 голосов
/ 21 ноября 2019

Невозможно преобразовать varchar в двоичный файл в операторе case. Раньше я считывал данные из 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)

enter image description here

1 Ответ

2 голосов
/ 21 ноября 2019

Проблема в вашем 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, и любые значения, возвращаемые из выражения CONVERT(varbinary(MAX), T.N.value('DocContent[1]', 'varchar(max)')), будут неявно приведение к 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 или NOT NULL, поэтому невозможно, чтобы одно из этих выражений не было истинным. Кроме того, из-за способа работы ISNULL (он возвращает тип данных 1-го параметра, он не использует приоритет типа данных), вам не нужно явно CONVERT последние значения:

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