我正在编写一些代码来查询一些DMV。某些列可能存在于 DMV 中,也可能不存在,具体取决于 SQL 版本。我在网上发现了一个有趣的建议,如何使用CROSS APPLY
跳过特定检查。
下面的查询是读取 DMV 中可能缺失的列的代码示例。该代码为该列创建一个默认值,并使用CROSS APPLY
从 DMV 中提取实际列(如果存在)。
代码尝试提取的列 BogusColumn 不存在。我希望下面的查询会生成有关无效列名的错误...但事实并非如此。它返回 NULL,没有错误。
为什么下面的 CROSS APPLY 子句不会导致“无效的列名”错误?
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;
如果我单独在CROSS APPLY
中运行查询:
select BogusColumn from sys.dm_exec_sessions;
我收到有关无效列名的预期错误:
Msg 207, Level 16, State 1, Line 9
Invalid column name 'BogusColumn'.
如果我将 DMV 列名称更改为 BogusColumn2 以使其唯一,则会收到预期的列名称错误:
select a.BogusColumn1, b.BogusColumn2
from
(
select cast(null as int) as BogusColumn1
) a
cross apply
(
select BogusColumn2 from sys.dm_exec_sessions
) b
我已在 SQL 2012 到 SQL 2017 版本上测试了此行为,并且该行为在所有版本中都是一致的。
最佳答案
BogusColumn 被定义为第一个查询中的有效列。
当我们应用交叉应用时,它使用列分辨率,如下所示:
1. 它在第二个查询 (dmv) 中查找“BogusColumn”列
2.如果dmv中存在该列,则解析为dmv
3. 如果 dmv 中不存在该列,它将在外部查询(顶部查询)中查找该列并使用那里提供的值。
换句话说,当 View 中未定义虚假列时,最终查询将按如下方式工作:
select * from
(
select cast(null as int) as BogusColumn
) a
cross apply
(
select a.BogusColumn AS BogusColumn from sys.dm_exec_sessions
) b;
如果已定义,查询将解析为:
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;
关于sql-server - 为什么 CROSS APPLY *不*在此查询中出现无效列错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58964952/