October 13, 2006 at 4:25 am
a colleague came to me with a problem earlier complaining that his query was NOT erroring when he thought it should, instead it was returning lots of rows he didnt expect (or want for that matter)
try the three following statements
select
colid from sysobjects
go
select
* from syscolumns where colid in (select colid from sysobjects)
go
select
* from syscolumns where colid in (select wibble from sysobjects)
go
i would expect them all to error because there is no colid or wibble in sysobjects, but it seems that sql server decides that because the column doesnt exist in the subquery that it should compare the text against the where clause instead. if the text is the same (second query) it will return all of the rows from the main select but if the text is different (third query) it errors with the column doesnt exist.
it's no problem but i am just curious if anyone can think of why it would work like that (in 2000 and in 2005)
October 13, 2006 at 5:10 am
That's really strange... I didn't know about this behaviour.
I tested this on a normal (user) table, and results are the same, so it isn't some idiosyncrasy of system tables.
If you look at the execution plan, you will see that the WHERE clause in query no. 2 is interpreted as "WHERE syscolumns.colid = syscolumns.colid".
I still don't know why this happens, and consider it as bug in SQLS, but now it is clear that you can avoid this problem if you stick to the recommended way of writing selects : always use table.column (or alias.column) to identify the column. Following query works as expected (i.e. fails with Invalid column name 'colid'.):
select * from syscolumns where colid in (select sysobjects.colid from sysobjects)
October 13, 2006 at 6:31 am
Maybe you just found the frontier between a correlated subquery and a subquery. Seems to make some sens but I agree that it should somehow error out if there's nothing "joining" the table together.
October 13, 2006 at 6:53 am
That's strange... I'm thinking we have a service pack problem here... I'll bet you guys are running SP4 on SQL Server 2000... I'm running SP3A... and here's what I get when I run Paul's queries...
Server: Msg 207, Level 16, State 3, Line 1 --From the first select
Invalid column name 'colid'.
(1578 row(s) affected)
Server: Msg 207, Level 16, State 3, Line 2 --From the thirde select
Invalid column name 'wibble'.
Has anyone checked the Microsoft site for a "known issue" or a "hot fix"?
--Jeff Moden
Change is inevitable... Change for the better is not.
October 13, 2006 at 6:55 am
hadnt noticed that in the execution plan. so it must be a bug then rather than it trying to assume something.
colleague is going to use joins now instead of being lazy and always using subqueries
October 13, 2006 at 6:58 am
actually i've tried it on sql2000 sp4, sql2005 without sp and with sp 1 and it happens on all of them
that is why i wasnt sure whether it was something that was happening for an intentional reason, but for the life of me i couldnt work out what that reason was.
October 13, 2006 at 6:59 am
http://support.microsoft.com/kb/q298674/
will give you your answer
Edit:
p.s. I always use fully-qualified column names in my subqueries
Far away is close at hand in the images of elsewhere.
Anon.
October 13, 2006 at 7:04 am
Crud... I didn't read the second query... sorry... not enough coffee...
To play on what David suggested... it's one of the reasons why I'm glad that the standards I wrote for work forbid the use of IN/SELECT instead of joining to a derived table.
--Jeff Moden
Change is inevitable... Change for the better is not.
October 13, 2006 at 7:33 am
Why forbid instead of educate?
Anyone into the habit of using fully qualified names (aka aliasing) their queries won't be caught unaware by this, which for those who have not read the link, is the expected 'by design and standards' behavior.
Admittedly, it's a tricky trap and easy to fall into, but as with most things, when things are done 'proper', many pitfalls also goes away.
/Kenneth
October 13, 2006 at 7:46 am
Thanks for the link, David. It is now clear that it isn't bug, but normal behaviour. I didn't think about it this way before - I supposed that the (select ...) part is independent on the rest, i.e. not correlated subquery, unless there is a corresponding statement in WHERE clause of the subquery. Wasn't aware that even this can be enough to make it correlated.
I'm happy that I always use qualified names... otherwise I'd have to go over all views and procedures and correct the code (actually I use derived tables now, but I know there are some older pieces of code which still contain IN(select..))
October 13, 2006 at 5:28 pm
Who needs to read that boring ANSI stuff?
_____________
Code for TallyGenerator
October 13, 2006 at 5:54 pm
Of course there's some education in it, Ken... but, it's still forbidden because it hurts performance and a derived table should be used instead. And, it will also catch these types of errors, as you know.
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply