2011-08-15 19 views
2

SQL Server 2008 Management Studioで次の問題が検出されました。次のスクリプトを全体として実行すると、エラーが発生する(「コピー&ペーストエラー」が原因である)ので、受け取ることはできません。SQL Tempテーブルがスローされない無効な列名エラーが発生したとき

IF OBJECT_ID('Foo') IS NOT NULL 
BEGIN 
    DROP TABLE Foo 
END 
IF OBJECT_ID('Bar') IS NOT NULL 
BEGIN 
    DROP TABLE Bar 
END 
CREATE TABLE Foo (
    FooID int 
) 
Create Table Bar (
    BarID int 
, FooID int 
) 
INSERT INTO Foo 
SELECT 1 UNION ALL SELECT 2 
INSERT INTO Bar 
SELECT 1,1 UNION ALL SELECT 2,1 UNION ALL SELECT 3,1 
GO 

IF OBJECT_ID('tempdb..#temp') IS NOT NULL 
BEGIN 
     DROP TABLE #TEMP 
END 
GO 
CREATE TABLE #TEMP (
    FooID int 
) 
INSERT INTO #TEMP 
    SELECT FooID FROM Bar 
GO 
SELECT * FROM Foo WHERE FooID IN (SELECT FooID FROM #TEMP) 
GO 
SELECT * FROM Bar WHERE BarID IN (SELECT BarID FROM #TEMP) 
GO 
SELECT * FROM #TEMP 
GO 

含む第二の最後の文は、「#TEMP FROM SELECT BarID」のwhere句のフィルタが実行されますが、#TEMPにはBarID列はありません。スクリプト全体を実行するとエラーはなく、スクリプトはFooのすべての行を返します。しかし、自分でコマンドを実行すると、#TEMPにBarIdがないことを知らせるエラーが表示されます。

これには理由がありますか?それは私のコードですか?

+1

BarIDが#TEMPにないことがわかっている場合、#TEMPからBarIDを選択する理由は何ですか? – Paparazzi

+0

私の質問では、私のところではエラーだと言いました。問題は私のコードがどれほど有効ではないのですが、なぜエラーがスローされなかったのですか?これはNeilによって回答されます – littlechris

答えて

4

最後の2番目のクエリが実際に正しく動作しています。

他のコメント作成者が私を修正してください。しかし、これは相関サブクエリであると私は理解しています。テーブルエイリアシングは実際に何が起こっているかを示します。ネストされたSELECT、#TEMPの行ごとに

SELECT * FROM Bar x WHERE x.BarID IN (SELECT x.BarID FROM #TEMP) 

実際、そうそう、(BarID)でBarIDが真である、テーブルバーからので、すべての行をBarIDの現在の値を返している:あなたのクエリがこれに相当しますBar内で一致するので、すべての行が返されます。

これは、私はあなたが期待していると思わエラーが発生します

SELECT * FROM Bar WHERE BarID IN (SELECT NonExistentFieldName FROM #TEMP) 

を試してみてください、あなたはクレイジーじゃないことを示すために。ニールの答えのいくつかの背景については

+0

ありがとうNeil - それは意図しない相関サブクエリでした..完全な命名法、または少なくともテーブルの別名を使用する必要があります! – littlechris

+0

+1これは、誤ってテーブル全体を消去する可能性があるため、DELETEの状況では特に危険です。 –

+0

確かに - すべてのコードがDev/Test/Liveのステージングを経由する理由です:) – littlechris

0

、次のKB資料を参照してください。

http://support.microsoft.com/kb/298674

彼らが使用する例(それはそれはいけないことが表示されますけれどもそれが動作します)(あなたの例と非常によく似ています彼らはまた、テーブルの別名(多くの理由のために良い方法ですが、過去のコンパイルを得ることから、この問題を防止するであろう)を追加すると、クエリは、あなた本来、eと失敗しますことを示して

CREATE TABLE X1 (ColA INT, ColB INT) 
CREATE TABLE X2 (ColC INT, ColD INT) 
SELECT ColA FROM X1 WHERE ColA IN (Select ColB FROM X2) 

:)#TEMPテーブルのないもののxpected。

これは実際に列解決のANSI標準に準拠しており、変更されません(ErlandのSET STRICT_CHECKS ONを実装していない場合)。

このバグ(とエンジンがこのように動作するように持っている理由について、より多くの背景)不満がいくつか他の人:

http://connect.microsoft.com/SQL/feedback/details/542289/

http://connect.microsoft.com/SQL/feedback/details/422252/

http://connect.microsoft.com/SQL/feedback/details/126785/

をしなければなりません@ BalamBalamのコメントに同意する:あなたはなぜ無効なコードを書いていて、それが間違って有効であると訴えているのですか?

+0

詳細な回答はありがたいですが、私が最初に考えたのは、実行する代わりにエラーが発生したコードだったからです私の質問のタイトル...本当に私の質問に "不平"がどこにあるかわからない。 – littlechris

関連する問題