Wednesday, March 7, 2012

Is it a SQL's bug?

There is not a field named as 'CRSID' in the table TMatch but the SQL Server
would return all the records in table tcrsmgr:
SELECT *
FROM dbo.TCRSMGR
WHERE (CRSID IN
(SELECT CRSID
FROM TMatch
WHERE tDATE = dbo.fDateOf('2005-7-20')))This is correct behavior because the TCRSMGR.CRSID is used in the subquery.
To avoid ambiguity, qualify column names in the subquery with the desired
table name or alias like the example below. In this case, you'll get an
error because the TMatch.CRSID column doesn't exist.
SELECT *
FROM dbo.TCRSMGR
WHERE (CRSID IN
(SELECT TMatch.CRSID
FROM TMatch
WHERE TMatch.tDATE = dbo.fDateOf('2005-7-20')))
Hope this helps.
Dan Guzman
SQL Server MVP
"Half Nitto" <mails2me@.invalidemail.com> wrote in message
news:ud6vP6XlFHA.2852@.TK2MSFTNGP14.phx.gbl...
> There is not a field named as 'CRSID' in the table TMatch but the SQL
> Server would return all the records in table tcrsmgr:
> SELECT *
> FROM dbo.TCRSMGR
> WHERE (CRSID IN
> (SELECT CRSID
> FROM TMatch
> WHERE tDATE = dbo.fDateOf('2005-7-20')))
>|||This is expected behavior. The inner reference to CRSID does
not include a table alias or table name. As a result, it is resolved
as TMatch.CRSID if that column exists, and if not, to
TCRSMGR.CRSID, if that column exists (which it does -
if it did not, you would get an error).
You now have a correlated subquery, and for each row of
TCRSMGR, that correlated subquery is
SELECT TCRSMGR.CRSID FROM TMatch
WHERE tDATE = dbo.fDateOf('2005-7-20')
So long as CRSID has at least one row for which
tDATE = dbo.fDateOf('2005-7-20'), then the WHERE
clause of the entire query is true, and so all rows of
TCRSMGR will be returned.
Outer references must always be valid in subqueries,
or it would be impossible to write a correlated subquery.
For example, no one thinks it's a bug that this works (to
select the biggest order for each employee)
select OrderID, OrderDate, OrderTotal
from Orders as O1
where OrderTotal = (
select max(OrderTotal)
from Orders as O2
where O2.EmployeeID = O1.EmployeeID
)
The reference to O1.EmployeeID is perfectly valid.
Here, the O1 alias is required to avoid ambiguity, but
aliases can be omitted when there is no chance of
ambiguity, and unfortunately in your case, omitting the
alias caused a programming error to go unnoticed.
Here's another example that might not seem so surprising
if not useful:
select * from T
where thisColumn = (
select T.thisColumn
)
You would expect this to return all rows of T with
non-null thisColumn values. Though there is not
even a table mentioned in the subquery, the reference
to T.thisColumn is valid and correlates with the rows
of the outer query. Since thisColumn would not be
ambiguous here, the same query can be written as
select * from T
where thisColumn = (
select thisColumn
)
or, if table X has at least one row,
select * from T
where thisColumn = (
select thisColumn from X
)
The moral of the story? In queries that refer to more
than one table, if not always, qualify columns with the
table you think they come from.
Had you done this here, and written
SELECT *
FROM dbo.TCRSMGR
WHERE (dbo.TCRSMGR.CRSID IN
(SELECT TMatch.CRSID
FROM TMatch
WHERE TMatch.tDATE = dbo.fDateOf('2005-7-20')))
you would have caught the programming error. Most all programming
languages are like this, in allowing inner declarations to override outer
ones, while allowing all outer declarations to be visible within sub-blocks,
if there is no shadowing inner declaration.
int i, j;
...
{
int i, k;
// you can refer to i, j and k here. j refers to the variables declared
// in the outer block, and i and k refers to the variable declared in
// the inner block.
Steve Kass
Drew University
Half Nitto wrote:

>There is not a field named as 'CRSID' in the table TMatch but the SQL Serve
r
>would return all the records in table tcrsmgr:
>SELECT *
>FROM dbo.TCRSMGR
>WHERE (CRSID IN
> (SELECT CRSID
> FROM TMatch
> WHERE tDATE = dbo.fDateOf('2005-7-20')))
>
>|||Have a look at
http://toponewithties.blogspot.com/...es_archive.html
Roji. P. Thomas
Net Asset Management
https://www.netassetmanagement.com
"Half Nitto" <mails2me@.invalidemail.com> wrote in message
news:ud6vP6XlFHA.2852@.TK2MSFTNGP14.phx.gbl...
> There is not a field named as 'CRSID' in the table TMatch but the SQL
> Server would return all the records in table tcrsmgr:
> SELECT *
> FROM dbo.TCRSMGR
> WHERE (CRSID IN
> (SELECT CRSID
> FROM TMatch
> WHERE tDATE = dbo.fDateOf('2005-7-20')))
>

No comments:

Post a Comment