Last few days I have hit myself into Oracle "feature" which was one of my favorite when I was helping developers solve strange Oracle issues. I recall one Oracle ANSI SQL syntax issue when Oracle didn't recognize that column names are duplicated in different tables and use a random one in output. This is why I always told people use column name with table name to avoid confusion. Anyway now I decided to blog about that and show why table.column_name syntax is so important.
Let's go through an example - In this syntax equal ?
select name1 from T1 where id1 in (select id1 from T2 where name2='NAME2');
select T1.name1 from T1 where T1.id1 in (select T2.id1 from T2 where name2='NAME2');
Looks OK isn't it ? But it really depend on how tables are defined.
SQL> desc T1 Name Null? Type ----------------------------------------- -------- ---------------------------- ID1 NUMBER NAME1 VARCHAR2(100) SQL> desc T2 Name Null? Type ----------------------------------------- -------- ---------------------------- ID2 NUMBER NAME2 VARCHAR2(100) SQL> select id1, name1 from T1; ID1 NAME1 ---------- ------------------------------------------------------- 1 NAME1 SQL> select id2, name2 from T2; ID2 NAME2 ---------- ------------------------------------------------------- 2 NAME2
Now we can see that there is a typo in second query as there is no ID1 column in T2 table. But lets try to execute both. First we start a query with tablename.columnname syntax :
SQL> select T1.name1 from T1 where T1.id1 in (select T2.id1 from T2 where name2='NAME2'); select T1.name1 from T1 where T1.id1 in (select T2.id1 from T2 where name2='NAME2') * ERROR at line 1: ORA-00904: "T2"."ID1": invalid identifierLooks OK Oracle found our error and query has not been executed. What about first example ?
SQL> select name1 from T1 where id1 in (select id1 from T2 where name2='NAME2'); NAME1 -------------------------------------------------------------------------------- NAME1 SQL>
It return one row and Oracle didn't find our typing error. Even worse IN filter is true for every T1 row but it should not - if you check rows in T1 and T2 where is no common value between ID1 and ID2.
Why ? We are going to check if ID1 from T1 is included in set of ID1 from T2. But there is no ID1 in T2 so Oracle is using ID1 from T1 as in every correlated subquery. What this subquery return ? It will return ID1 from table T1 for every row in table T2 where name is equal to 'NAME2'. This is not what was excepted.
But is this subquery can be executed as separate query ? Of course not
Why ? We are going to check if ID1 from T1 is included in set of ID1 from T2. But there is no ID1 in T2 so Oracle is using ID1 from T1 as in every correlated subquery. What this subquery return ? It will return ID1 from table T1 for every row in table T2 where name is equal to 'NAME2'. This is not what was excepted.
But is this subquery can be executed as separate query ? Of course not
SQL> select id1 from T2 where name2='NAME2'; select id1 from T2 where name2='NAME2' * ERROR at line 1: ORA-00904: "ID1": invalid identifier
I'm not sure if that problem can be classified as bug but at least is good to know how Oracle is using columns names and use tablename.columnname syntax to avoid confusion and increase code quality. Especially if there are tables with long column names and there is one letter difference between them.
regards,
Marcin