ORACLE 12.2.01 выбор столбцов из разных таблиц с похожими именами -> используется внутренний идентификатор столбца - PullRequest
2 голосов
/ 05 мая 2020

Я написал SELECT, выполняющий UNION, и в каждой части UNION, используя несколько JOIN. Объединяемые таблицы имеют частично одинаковые идентификаторы столбцов. И если выполняется «SELECT *», ORACLE решает отобразить внутренние имена столбцов вместо «реальных» имен столбцов.

Чтобы показать эффект, я создал две таблицы (с частично похожими идентификаторами столбцов, «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 * 
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

Когда оператор записывается с именами таблиц для указания столбцов, все работает так, как я ожидал:

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

Кто-нибудь может это объяснить?

Я расширил свои тесты еще двумя таблицами, чтобы предотвратить двойное использование таблицы в операторе:

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 использует внутренние идентификаторы.

Ответы [ 2 ]

1 голос
/ 05 мая 2020

Согласно Oracle (DocId 2658003.1), это происходит при соблюдении трех условий:

  1. ANSI join
  2. UNION / UNION ALL
  3. то же таблица появляется более одного раза в запросе

По-видимому, «QCSJ_ C» используется внутри, когда Oracle преобразует соединения в стиле ANSI.

EDIT:

Нашел минимальный пример:

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
0 голосов
/ 05 мая 2020

Интересно!

Однако я бы никогда не стал использовать оператор набора (UNION, UNION ALL, INTERSECT, MINUS) вместе со звездочкой (*).

Порядок столбцов может измениться, возможно, не вами, а кем-то, кто занимается обслуживанием базы данных, или путем переноса вашей базы данных в новую систему с помощью экспорта / импорта и т.д. c. Простой пример:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...