ORACLE 12.2.01 从具有相似名称的不同表中选择列 --> 使用内部列标识符

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

我写了一个 SELECT 执行 UNION 并在每个 UNION 部分使用一些 JOIN。连接的 tables 具有部分相同的列标识符。 如果执行 "SELECT *",ORACLE 决定显示内部列名而不是 "real" 列名。

为了显示效果,我创建了两个 table(具有部分相似的列标识符,"TID" 和 "TNAME")并用一些数据填充它们:

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);

我 SELECT之后使用以下语句对列进行编辑:

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;

得到了这个令人困惑的结果:

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

当使用 tablenames 编写语句来指定列时,一切都如我所料:

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

谁能解释一下?

我用另外两个 table 扩展了我的测试,以防止在语句中重复使用 table:

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;

结果是一样的。 Oracle 使用内部标识符。

根据 Oracle (DocId 2658003.1),当满足三个条件时会发生这种情况:

  1. ANSI 加入
  2. 联合/联合所有
  3. 相同的table在查询中出现不止一次

显然,"QCSJ_C" 在 Oracle 转换 ANSI 样式连接时在内部使用。

编辑:

找到一个最小的例子:

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

可以通过使用非 ANSI 连接语法来解决:

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

或者,最好使用列名而不是 *:

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

有趣!

但是,我永远不会将集合运算符 (UNIONUNION ALLINTERSECTMINUS) 与星号 (*) 一起使用.

列的顺序可以更改,可能不是由您更改,而是由维护数据库的人更改,或者使用 export/import 将您的数据库迁移到新系统等。简单示例:

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