问题
Why does SQL server behave this way. I am running this on SQL 2005.
The IN clause does not validate the column names in the sub query but validates it against the table name in the outer query. Here is an example of getting
Create table #table1(col1 int, col2 char(10), col3 char(15));
Create table #table2(col10 int, col11 char(10), col2 char(15));
insert into #table1(col1, col2, col3)
select 1, 'one', 'three'
insert into #table1(col1, col2, col3)
select 2, 'two', 'three'
insert into #table1(col1, col2, col3)
select 3, 'three', 'four'
insert into #table2(col10, col11, col2)
select 1, 'one', 'three'
insert into #table2(col10, col11, col2)
select 2, 'two', 'three'
insert into #table2(col10, col11, col2)
select 3, 'three', 'four'
select * from #table1
where col1 IN
(select col1 from #table2)
Where as if I just select the "select col1 from #table2" and run it spits an error
Msg 207, Level 16, State 1, Line 1
Invalid column name 'col1'.
回答1:
Why? Because it's frequently useful to be able to reference columns from the outer query in subqueries. There's no setting you can use to turn off this behaviour, but if you get into the habit of using aliases, you should avoid most problems with it:
select * from #table1 t1
where t1.col1 IN
(select t2.col1 from #table2 t2)
Will produce an error.
回答2:
It's not the IN clauses that's the problem.
This:
SELECT *
FROM #table1
WHERE col1 IN (SELECT col1
FROM #table2)
...works, because the optimizer is assumes col1 to be from #table1. If you use table aliases so there's no ambiguity:
SELECT t1.*
FROM #table1 t1
WHERE t1.col1 IN (SELECT t2.col1
FROM #table2 t2)
...you'll get the Msg 207: Invalid column error.
This is the same principle as when working with DELETE and UPDATE statements, because the typical syntax doesn't allow you to alias the table being deleted or updated.
来源:https://stackoverflow.com/questions/12319185/using-the-dangerous-in-clause-in-sql