问题
I am writing some code to query some DMVs. Some of the columns may or may not exist in the DMV depending on SQL version. I found an interesting suggestion online how to skip specific checking using CROSS APPLY
.
The query below is an example of code to read a DMV for a potentially missing column. The code creates a default value for the column and uses CROSS APPLY
to extract the actual column, if it exists, from the DMV.
The column the code tries to extract, BogusColumn, does not exist. I would expect the query below to generate an error about an invalid column name... but it does not. It returns NULL without error.
Why does the CROSS APPLY clause below NOT result in an "invalid column name" error?
declare @x int
select @x = b.BogusColumn
from
(
select cast(null as int) as BogusColumn
) a
cross apply
(
select BogusColumn from sys.dm_exec_sessions
) b;
select @x;
If I run the query in the CROSS APPLY
separately:
select BogusColumn from sys.dm_exec_sessions;
I get an expected error about an invalid column name:
Msg 207, Level 16, State 1, Line 9
Invalid column name 'BogusColumn'.
If I change the DMV column name to BogusColumn2 to make it unique, I get the expected column name error:
select a.BogusColumn1, b.BogusColumn2
from
(
select cast(null as int) as BogusColumn1
) a
cross apply
(
select BogusColumn2 from sys.dm_exec_sessions
) b
I have tested this behavior on versions of SQL 2012 through SQL 2017, and the behavior is consistent across all versions.
回答1:
BogusColumn is defined as a valid column in the 1st query.
When we are applying cross apply, it is using column resolution as follow:
1. It looks for the column 'BogusColumn' in the 2nd query (dmv)
2. If the column exists in the dmv, it will be resolved to the dmv
3. If the column do not exists in the dmv, it will look for this column in the outer query (the top one) and use value provided there.
In other words when bogus column is not defined in the view the final query will work as:
select * from
(
select cast(null as int) as BogusColumn
) a
cross apply
(
select a.BogusColumn AS BogusColumn from sys.dm_exec_sessions
) b;
If it is defined, query will resolve to:
select * from
(
select cast(null as int) as BogusColumn
) a
cross apply
(
select s.BogusColumn AS BogusColumn from sys.dm_exec_sessions as s
) b;
来源:https://stackoverflow.com/questions/58964952/why-does-cross-apply-not-get-an-invalid-column-error-in-this-query