ORACLE 12.2.01 selecting columns from different tables with similar names --> internal column identifier used

眉间皱痕 提交于 2021-01-28 03:50:49

问题


I wrote a SELECT performing a UNION and in each UNION part using some JOINs. The tables, which are joined have partly the same column identifiers. And if a "SELECT *" is performed, ORACLE decides to display the internal column names instead of the "real" column names.

To show the effect I created two tables (with partly similar column identifiers, "TID" and "TNAME") and filled them with some data:

create table table_one (tid number(10), tname varchar2(10), t2id number(10));
create table table_two (tid number(10), tname varchar2(10));

insert into table_two values (1,'one');
insert into table_two values (2,'two');
insert into table_two values (3,'three');

insert into table_one values (1,'eins',1);
insert into table_one values (2,'zwei',2);
insert into table_one values (3,'drei',3);

The I SELECTED the columns afterwards with the following statement:

select * 
from table_one 
inner join table_two on table_two.tid = table_one.t2id
where table_one.tid = 1
union
select * 
from table_one 
inner join table_two on table_two.tid = table_one.t2id
where table_one.tid = 2;

And got this confusing result:

QCSJ_C000000000300000 QCSJ_C000000000300002       T2ID QCSJ_C000000000300001 QCSJ_C000000000300004
                    1 eins                           1                     1 one
                    2 zwei                           2                     2 two

When the statement is written with tablenames to specify the columns, everything works as I expected:

select table_one.* , table_two.*
from table_one 
inner join table_two on table_two.tid = table_one.t2id
where table_one.tid = 1
minus
select * 
from table_one 
inner join table_two on table_two.tid = table_one.t2id
where table_one.tid = 2;
   TID TNAME            T2ID        TID TNAME
     1 eins                1          1 one
     2 zwei                2          2 two

Can anybody explain that?

I expanded my tests with two more tables to prevent double usage of table in the statement:

create table table_3 (tid number(10), tname varchar2(10), t4id number(10));
create table table_4 (tid number(10), tname varchar2(10));

insert into table_4 values (1,'one');
insert into table_4 values (2,'two');
insert into table_4 values (3,'three');

insert into table_3 values (1,'eins',1);
insert into table_3 values (2,'zwei',2);
insert into table_3 values (3,'drei',3);

select * 
from table_one 
inner join table_two on table_two.tid = table_one.t2id
where table_one.tid = 1
union
select * 
from table_3
inner join table_4 on table_4.tid = table_3.t4id
where table_3.tid = 2;

select * 
from table_one 
inner join table_two on table_two.tid = table_one.t2id
where table_one.tid = 1
union
select * 
from table_3
inner join table_4 on table_4.tid = table_3.t4id
where table_3.tid = 2;

The result is the same. Oracle uses internal identifiers.


回答1:


According to Oracle (DocId 2658003.1), this happens when three conditions are met:

  1. ANSI join
  2. UNION / UNION ALL
  3. the same table appears more than once in the query

Aparently, "QCSJ_C" is used internally when Oracle transforms ANSI style joins.

EDIT:

Found a minimal example:

SELECT * FROM dual d1 JOIN dual d2 ON d1.dummy=d2.dummy
UNION
SELECT * FROM dual d1 JOIN dual d2 ON d1.dummy=d2.dummy;

QCSJ_C000000000300000 QCSJ_C000000000300001
X                     X

It can be fixed by either using non-ANSI join syntax:

SELECT * FROM dual d1, dual d2 WHERE d1.dummy=d2.dummy
UNION
SELECT * FROM dual d1, dual d2 WHERE d1.dummy=d2.dummy;

DUMMY DUMMY_1
X     X

Or, preferably by using column names instead of *:

SELECT d1.dummy, d2.dummy FROM dual d1 JOIN dual d2 ON d1.dummy=d2.dummy
UNION
SELECT d1.dummy, d2.dummy FROM dual d1 JOIN dual d2 ON d1.dummy=d2.dummy;

DUMMY DUMMY_1
X     X



回答2:


Interesting!

However, I would never use a set operator (UNION, UNION ALL, INTERSECT, MINUS) together with an asterisk (*).

The order of columns can change, maybe not by you but by somebody doing maintenance on the database, or by migrating your database to a new system using export/import, etc. Simple example:

CREATE TABLE t (a INT, b INT, c INT);
SELECT * FROM t;
A B C

ALTER TABLE t MODIFY b INVISIBLE;
ALTER TABLE t MODIFY b VISIBLE;
SELECT * FROM t;
A C B


来源:https://stackoverflow.com/questions/61611705/oracle-12-2-01-selecting-columns-from-different-tables-with-similar-names-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!