2017-06-16 77 views
0

问题在于引用不在存储过程中的表变量内的列名称。我会假设这应该产生了一个错误,但它返回值,而列名称在主查询中找到。使用无效列名称的表变量TSQL问题

这是一个已知问题,可能在SQL 2016中修复?或者是预期这种行为?

DECLARE @LookupTable TABLE(MyId Integer, PRIMARY KEY(MyId)); 
INSERT INTO @LookupTable (MyId) Values (1); 


DECLARE @DataTable TABLE(My_Id Integer, MyOtherField Char(1), PRIMARY KEY(My_Id)); 
INSERT INTO @DataTable (My_Id,MyOtherField) Values (1,'A'); 
INSERT INTO @DataTable (My_Id,MyOtherField) Values (2,'B'); 
INSERT INTO @DataTable (My_Id,MyOtherField) Values (3,'C'); 


--SELECT MyId works as expected (one row) 
SELECT MyOtherField FROM @DataTable 
WHERE My_Id IN (SELECT MyId FROM @LookupTable) 

--SELECT My_Id should be an error 
--Returns three rows when referencing a column name not in @LookupTable 
SELECT MyOtherField FROM @DataTable 
WHERE My_Id IN (SELECT My_Id FROM @LookupTable) 

--Returns expected error: invalid column name 'My_Id' 
SELECT My_Id FROM @LookupTable 

SQL Server 2014(SP2)。

+0

我以前见过这种行为,从这个意义上说它是预期的......如果你正确地识别列(即:从@DataTable DT DT.My_id等),你会得到逻辑预期的结果。 – HoneyBadger

+1

这是完全预期的。在你认为应该是错误的查询中,子查询实际上是使用@DataTable中的My_Id,而不是你认为的MyId。这是一个经典的例子,为什么它引用每个列与表(或最好是别名)以避免此问题非常重要。 –

回答

2

M_Id在子查询中的列是从外部表@DataTable引用的。它被称为相关的子查询。在子查询中可以引用外部表中的列。

现在它会更有意义。

SELECT MyOtherField FROM @DataTable T 
WHERE T.My_Id IN (SELECT T.My_Id FROM @LookupTable) 

当使用exists时,大多使用相关的子查询。你可以看到在Where条款从外部表中的列将被称为

+0

当然,这是非常有意义的...但是当看到一个更大的部分,它通过我一个循环。必须今天早上把眼罩关掉...... –

+0

@DarianMiller - 完美有效的问题。我看到很多人提出类似的问题 –

1

[1]报道的“问题”的更多细节:当前问题认为,下面的查询

SELECT MyOtherField FROM @TableA 
WHERE ColumnFromTableA IN (SELECT ColumnFromTableA FROM @TableB) 

返回意想不到的结果。

[2]这不是一个错误。

[3]这是预期的行为:它DBMS局部范围的@TableB将与成功,如果此列内@TableA存在执行(无警告/异常)内未找到ColumnFromTableA(如SQL服务器)。