35

I have two tables, table_a (id, name) and table_b (id), let's say on Oracle 12c.

Why does this query not return an exception?

select * from table_a where name in (select name from table_b);

From what I understand, Oracle sees this as

select * from table_a where name = name;

But what I don't get is why?

Mark Stewart's user avatar
Mark Stewart
1,1701 gold badge13 silver badges32 bronze badges
askedJun 27, 2016 at 8:27
eagerMoose's user avatar
0

3 Answers3

59

The query is syntactically correct SQL even iftable_b does not have aname column. The reason is scope resolution.

When the query is parsed, it is first checked whethertable_b has aname column. Since it doesn't, thentable_a is checked. It would throw an error only if neither of the tables had aname column.

Finally the query is executed as:

select a.* from table_a  awhere a.name in (select a.name                  from table_b  b                );

As for the results the query would give, for every row oftable_a, the subquery(select name from table_b) - or(select a.name from table_b b) - is a table with a single column with the samea.name value and as many rows astable_b. So, iftable_b has 1 or more rows, the query runs as:

select a.* from table_a  awhere a.name in (a.name, a.name, ..., a.name) ;

or:

select a.* from table_a  awhere a.name = a.name ;

or:

select a.* from table_a  awhere a.name is not null ;

Iftable_b is empty, the query will return no rows (thnx to @ughai for pointing that possibility).


That (the fact that you don't get an error) is probably the best reason that all column references should be prefixed with the table name/alias. If the query was:

select a.* from table_a where a.name in (select b.name from table_b);

you would have got the error straight away. When table prefixes are omitted, it is not difficult for such mistakes to happen, especially in more complex queries, and even more important, go unnoticed.

Read also inOracle docs: Resolution of Names in Static SQL Statements the similar example B-6 inInner capture and the recommendations in theAvoiding Inner Capture in SELECT and DML Statements paragraphs:

Qualify each column reference in the statement with the appropriate table alias.

answeredJun 27, 2016 at 9:18
ypercubeᵀᴹ's user avatar
1
  • How did you dissect the inner workings of the SQL engine so accurately?CommentedFeb 16, 2019 at 14:54
7

Because

Oracle performs a correlated subquery when a nested subquery references a column from a table referred to a parent statement one level above the subquery.http://docs.oracle.com/cd/E11882_01/server.112/e41084/queries007.htm#SQLRF52357

It means in order to determine whether subquery is correlated Oraclemust try to resolve names in subquery including outer statement context too. And for unprefixedname it's the only resolution possible.

answeredJun 27, 2016 at 9:24
Serg's user avatar
4

There is noname field intable_b so Oracle takes the one fromtable_a. I tried theEXPLAIN PLAN but this gave me only that there is aTABLE ACCESSFULL. I presume that this will generate some kind of Cartesian Product between both tables that result in a list of all the names intable_a is returned by the sub-query.

answeredJun 27, 2016 at 8:53
Marco's user avatar
3
  • 5
    "There is no name field in table_b so Oracle takes the one from table_a." Correct."I presume that this will generate some kind of Cartesian Product." Wrong. The query hasfrom table_a where .... It will return all rows fromtable_a except those thatname is null.CommentedJun 27, 2016 at 9:04
  • 1
    TABLE ACCESS FULL is just Oracle's way of telling you it's doing a sequential scan.CommentedJun 27, 2016 at 15:51
  • 1
    Your PLAN is irrelevant - there may well be indexing with huge tables - I'm assuming that your running on test data?CommentedJun 27, 2016 at 18:02

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.