对于 xml 路径 returns null 而不是什么都没有
For xml path returns null instead of nothing
我认为下面的查询假设 return 什么都没有,但是,相反,它 return 是一条记录,其中一列包含 null
:
select *
from ( select 1 as "data"
where 0 = 1
for xml path('row') ) as fxpr(xmlcol)
如果您 运行 只是子查询 - 什么都没有 returned,但是当这个子查询有一个外部查询时,对其执行 select
,null
是returned.
为什么会这样?
空 XML 数据在 SQL 服务器中被视为 NULL。
select *
from ( select 1 as "data"
where 0 = 1
for xml path('row') ) as fxpr(xmlcol)
子查询将首先执行,子查询的结果即 (Empty Rowset) 将转换为 XML 因此,得到 NULL 值。
SQL 服务器将尝试预测 类型。看看这个
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';
结果returns"IsThereAType?"为INT
! (我很确定这是相当随机的,在您的系统上可能会有所不同。)
顺便说一句:如果没有最后一个块,类型是 VARCHAR(3)
...
现在回答你的问题
A naked 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)
一样,包裹在子 select returns 中。 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:
中放置一个naked标量
SELECT * FROM('blah') AS x(y) --fails
虽然这没关系
SELECT * FROM(SELECT 'blah') AS x(y)
结论:
在您的特殊情况下,查询解析器似乎略有不一致:
虽然子select不能只包含一个标量值,但SELECT ... FOR XML
(实际上返回一个标量)不会被拒绝。引擎似乎将此解释为 SELECT
返回 标量值。这完全没问题。
这对于嵌套的子 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;
我认为下面的查询假设 return 什么都没有,但是,相反,它 return 是一条记录,其中一列包含 null
:
select *
from ( select 1 as "data"
where 0 = 1
for xml path('row') ) as fxpr(xmlcol)
如果您 运行 只是子查询 - 什么都没有 returned,但是当这个子查询有一个外部查询时,对其执行 select
,null
是returned.
为什么会这样?
空 XML 数据在 SQL 服务器中被视为 NULL。
select *
from ( select 1 as "data"
where 0 = 1
for xml path('row') ) as fxpr(xmlcol)
子查询将首先执行,子查询的结果即 (Empty Rowset) 将转换为 XML 因此,得到 NULL 值。
SQL 服务器将尝试预测 类型。看看这个
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';
结果returns"IsThereAType?"为INT
! (我很确定这是相当随机的,在您的系统上可能会有所不同。)
顺便说一句:如果没有最后一个块,类型是 VARCHAR(3)
...
现在回答你的问题
A naked 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)
一样,包裹在子 select returns 中。 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:
SELECT * FROM('blah') AS x(y) --fails
虽然这没关系
SELECT * FROM(SELECT 'blah') AS x(y)
结论:
在您的特殊情况下,查询解析器似乎略有不一致:
虽然子select不能只包含一个标量值,但SELECT ... FOR XML
(实际上返回一个标量)不会被拒绝。引擎似乎将此解释为 SELECT
返回 标量值。这完全没问题。
这对于嵌套的子 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;