sql-server - 为什么 CROSS APPLY *不*在此查询中出现无效列错误?

标签 sql-server tsql cross-apply

我正在编写一些代码来查询一些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/

相关文章:

sql-server - SQL-获取具有最大值的列的索引

SQL Server 转换选择一列并将其转换为字符串

sql - 更新为最新日期

.net - SqlBulkCopy 与 SqlBulkCopy 的比较TVP VS。 XML 参数对比20-200 个插入的单独插入过程?

使用带有删除语句的交叉应用的 T-SQL

Mysql ISNUMERIC() 如何可用?

sql - varchar(500) 比 varchar(8000) 有优势吗?

sql-server - SQL : find continuous date ranges across multiple rows?

mysql - 根据另一个表的查询获取表的行

sql - 什么时候应该使用 CROSS APPLY 而不是 INNER JOIN?