I thought that following query suppose to return nothing, but, instead, it returns one record with a column containing null
:
select *
from ( select 1 as "data"
where 0 = 1
for xml path('row') ) as fxpr(xmlcol)
If you run just the subquery - nothing is returned, but when this subquery has an outer query, performing a select
on it, null
is returned.
Why is that happening?
SQL Server will try to predict the type. Look at this
The first column will be predicted as string type, while the second is taken as
INT
. That's why the+
operator on top works. Try to add a number to the first or a string to the second. This will fail.Try to uncomment the last block and it will fail too.
The prediction is done at a very early stage. Look at this, where I did include the third
UNION ALL
(invalid query, breaking the type):The result returns "IsThereAType?" as
INT
! (I'm pretty sure this is rather random and might be different on your system.)Btw: Without this last block the type is
VARCHAR(3)
...Now to your question
A naked XML is taken as
NTEXT
(altough this is deprecated!) and needs,TYPE
to be predicted asXML
:The same wrapped within a sub-select returns as
NVARCHAR(MAX)
resp.XML
Well, this is a bit weird actually... An XML is a scalar value taken as
NTEXT
,NVARCHAR(MAX)
orXML
(depending on the way you are calling it). But it is not allowed to place a naked scalar in a sub-select:While this is okay
Conclusio:
The query parser seems to be slightly inconsistent in your special case:
Although a sub-select cannot consist of one scalar value only, the
SELECT ... FOR XML
(which returs a scalar actually) is not rejected. The engine seems to interpret this as aSELECT
returning a scalar value. And this is perfectly okay.This is usefull with nested sub-selects as a column (correlated sub-queries) to nest XML:
Without the
FOR XML
clause this would fail (...more than one value... / ...Only one column...)Pass a generic
SELECT
as a parameter?Some would say this is not possible, but you can try this: