Tsql SQL临时表在应该时未引发无效列名错误
我在SQLServer2008ManagementStudio中发现了以下问题。当我整体运行下面的脚本时,我预计会由于复制和粘贴错误而出现错误,但不会收到这些错误Tsql SQL临时表在应该时未引发无效列名错误,tsql,sql-server-2008,Tsql,Sql Server 2008,我在SQLServer2008ManagementStudio中发现了以下问题。当我整体运行下面的脚本时,我预计会由于复制和粘贴错误而出现错误,但不会收到这些错误 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 Tabl
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
包含SELECT BarID FROM TEMP上where子句筛选器的最后一条语句运行,但TEMP中没有BarID列。当作为一个整体运行脚本时,我没有收到任何错误,脚本返回Foo中的所有行。然而,当我自己运行命令时,我会得到一个错误,通知我TEMP中没有BarId
这有什么原因吗?这是我的代码吗?您的倒数第二个查询实际上工作正常 其他评论请纠正我,但我理解这是一个相关的子查询。表别名将显示实际发生的情况。您的查询相当于:
SELECT * FROM Bar x WHERE x.BarID IN (SELECT x.BarID FROM #TEMP)
对于TEMP中的每一行,嵌套的select实际上是从表Bar返回BarID的当前值,所以是的,BarID中的BarID为true,所以Bar中的每一行都是匹配的,所以返回每一行
为了证明你不是疯子,试试看
SELECT * FROM Bar WHERE BarID IN (SELECT NonExistentFieldName FROM #TEMP)
这就产生了我认为您所期待的错误。有关Neil答案的一些背景信息,请参阅以下KB文章: 他们使用的示例虽然看起来不应该与您的示例非常相似,但没有临时表:
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)
它们还表明,添加表别名是一种很好的做法,这有很多原因,但可以防止这个问题通过编译,这会使查询像您最初预期的那样失败
这实际上遵循了ANSI的列分辨率标准,并且不会改变,除非他们实现了Erland的
其他一些人抱怨此错误,并对引擎为何必须以这种方式工作提供了更多背景信息:
必须同意@BalamBalam的评论:为什么您编写无效代码,然后抱怨错误地将其视为有效代码?如果您知道BarID不在TEMP中,为什么您要从TEMP中选择BarID?正如我在问题中所说,这是我的一个错误-问题不是我的代码有多有效,而是为什么没有抛出错误。。。。Neil回答了这个问题-这是一个意外的相关子查询。。需要使用完整命名,或者至少使用表别名+1这在删除情况下尤其危险,因为它会导致您无意中清除整个表。当然-这就是为什么所有代码都要经过Dev/Test/Live staging:我感谢您的详细回答,但是我问的原因是因为我最初的想法是代码应该抛出一个错误而不是运行-因此我的问题标题。。。我不太清楚我的问题是什么。