2017-06-16 81 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服務器)。