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;