Для XML путь возвращает ноль вместо ничего - PullRequest
0 голосов
/ 17 мая 2018

Я подумал, что следующий запрос предполагает ничего не возвращать, но вместо этого он возвращает одну запись со столбцом, содержащим null:

select *
from ( select 1 as "data"
       where 0 = 1
       for xml path('row') ) as fxpr(xmlcol)

Если вы запускаете только подзапрос - ничего не возвращается, нокогда у этого подзапроса есть внешний запрос, выполняющий select, возвращается null.

Почему это происходит?

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

SQL Server попытается предсказать тип. Посмотри на это

SELECT tbl.[IsThereAType?] + '_test'
      ,tbl.ThisIsINT       + 100
FROM
(
    SELECT NULL AS [IsThereAType?]
          ,3 AS ThisIsINT
    UNION ALL 
    SELECT 'abc'
          ,NULL
    --UNION ALL 
    --SELECT 1  
    --    ,NULL
) AS tbl;

Первый столбец будет прогнозируемым в качестве строкового типа, а второй - как INT. Вот почему оператор + сверху работает. Попробуйте добавить число к первому или строку ко второму. Это не удастся.

Попробуйте раскомментировать последний блок, и он тоже потерпит неудачу.

предсказание сделано на очень ранней стадии. Посмотрите на это, где я включил третий UNION ALL (неверный запрос, нарушающий тип):

EXEC sp_describe_first_result_set 
N'SELECT *
FROM
(
    SELECT NULL AS [IsThereAType?]
          ,3 AS ThisIsINT
    UNION ALL 
    SELECT ''abc''
          ,NULL
    UNION ALL 
    SELECT 1
          ,NULL

) AS tbl';

Результат возвращает "IsThereAType?" как INT! (Я почти уверен, что это довольно случайно и может отличаться в вашей системе.)
Кстати: без этого последнего блока тип является VARCHAR(3) ...

Теперь к вашему вопросу

A голый XML принимается за NTEXT (хотя это устарело!) И прогнозируется ,TYPE как XML:

EXEC sp_describe_first_result_set N'SELECT ''blah'' FOR XML PATH(''blub'')';
EXEC sp_describe_first_result_set N'SELECT ''blah'' FOR XML PATH(''blub''),TYPE';

То же, что заключено в подвыбор, возвращается как NVARCHAR(MAX) соотв. XML

EXEC sp_describe_first_result_set N'SELECT * FROM(SELECT ''blah'' FOR XML PATH(''blub'')) AS x(y)';
EXEC sp_describe_first_result_set N'SELECT * FROM(SELECT ''blah'' FOR XML PATH(''blub''),TYPE) AS x(y)';

Ну, на самом деле это немного странно ... XML - это скалярное значение , принимаемое как NTEXT, NVARCHAR(MAX) или XML (в зависимости от способа его вызова). Но не разрешается помещать обнаженный скаляр в под-выбор:

SELECT * FROM('blah') AS x(y) --fails

Пока все нормально

SELECT * FROM(SELECT 'blah') AS x(y)    

Conclusio:

Парсер запросов выглядит немного противоречивым в вашем особом случае:

Хотя дополнительный выбор не может состоять только из одного скалярного значения, SELECT ... FOR XML (который фактически возвращает скаляр) не отклоняется. Кажется, двигатель интерпретирует это как SELECT , возвращающее скалярное значение. И это совершенно нормально.

Это полезно с вложенными вложенными выборками в качестве столбца (коррелированные вложенные запросы) для вложения XML:

SELECT TOP 5 t.TABLE_NAME
            ,(
              SELECT COLUMN_NAME,DATA_TYPE 
              FROM INFORMATION_SCHEMA.COLUMNS AS c
              WHERE c.TABLE_SCHEMA=t.TABLE_SCHEMA
                AND c.TABLE_NAME=t.TABLE_NAME
              FOR XML PATH('Column'),ROOT('Columns'),TYPE
             ) AS AllTablesColumns
FROM INFORMATION_SCHEMA.TABLES AS t;

Без предложения FOR XML это не получится ( ... более одного значения ... / ... Только один столбец ... )

Передать универсальный SELECT в качестве параметра?

Кто-то скажет, что это невозможно, но вы можете попробовать это:

CREATE FUNCTION dbo.TestType(@x XML)
RETURNS TABLE
AS
RETURN
SELECT @x AS BringMeBack;
GO

--The SELECT must be wrapped in paranthesis!
SELECT *
FROM dbo.TestType((SELECT TOP 5 * FROM sys.objects FOR XML PATH('x'),ROOT('y')));
GO

DROP FUNCTION dbo.TestType;
0 голосов
/ 17 мая 2018

Пусто XML Данные обрабатываются как NULL в SQL Server.

select *
from ( select 1 as "data"
       where 0 = 1
       for xml path('row') ) as fxpr(xmlcol)

Сначала выполняется подзапрос, а результат подзапроса, т. Е. (Пустая строка) будет преобразовано в XML , следовательно, получит значение NULL .

...