Так называемый natural join
дает указание базе данных
- Найти все имена столбцов, общие для обеих таблиц (в данном случае
degreeprogram
и degreeprogram
, которые, конечно, имеют одинаковыестолбцы.) - Создание условия объединения для каждой пары совпадающих имен столбцов в форме
table1.column1 = table2.column1
(в этом случае для каждого столбца в degreeprogram
. будет один)
Поэтому запрос, подобный этому
select count(*) from demo natural join demo;
, будет преобразован в
select count(*) from demo, demo where demo.x = demo.x;
Я проверил это, создав таблицу с одним столбцом и двумя строками:
create table demo (x integer);
insert into demo values (1);
insert into demo values (2);
commit;
и затем отслеживание сеанса :
SQL> alter session set tracefile_identifier='demo_trace';
Session altered.
SQL> alter session set events 'trace [SQL_Compiler.*]';
Session altered.
SQL> select /* nj test */ count(*) from demo natural join demo;
COUNT(*)
----------
4
1 row selected.
SQL> alter session set events 'trace [SQL_Compiler.*] off';
Session altered.
Затем в файле twelve_ora_6196_demo_trace.trc я нашел следующую строку:
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT COUNT(*) "COUNT(*)" FROM "WILLIAM"."DEMO" "DEMO","WILLIAM"."DEMO" "DEMO" WHERE "DEMO"."X"="DEMO"."X"
и несколько строк спустя:
try to generate single-table filter predicates from ORs for query block SEL$58A6D7F6 (#0)
finally: "DEMO"."X" IS NOT NULL
(Это просто оптимизация поверх сгенерированного запроса выше, поскольку столбец X
может иметь значение NULL, но объединение позволяет оптимизатору сделать вывод, что требуются только ненулевые значения.t заменить соединения.)
Отсюда и план выполнения:
-----------------------------------------+-----------------------------------+
| Id | Operation | Name | Rows | Bytes | Cost | Time |
-----------------------------------------+-----------------------------------+
| 0 | SELECT STATEMENT | | | | 7 | |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
| 2 | MERGE JOIN CARTESIAN | | 4 | 52 | 7 | 00:00:01 |
| 3 | TABLE ACCESS FULL | DEMO | 2 | 26 | 3 | 00:00:01 |
| 4 | BUFFER SORT | | 2 | | 4 | 00:00:01 |
| 5 | TABLE ACCESS FULL | DEMO | 2 | | 2 | 00:00:01 |
-----------------------------------------+-----------------------------------+
Query Block Name / Object Alias(identified by operation id):
------------------------------------------------------------
1 - SEL$58A6D7F6
3 - SEL$58A6D7F6 / DEMO_0001@SEL$1
5 - SEL$58A6D7F6 / DEMO_0002@SEL$1
------------------------------------------------------------
Predicate Information:
----------------------
3 - filter("DEMO"."X" IS NOT NULL)
Альтернативаага, давайте посмотрим, что с этим делает dbms_utility.expand_sql_text
.Я не совсем уверен, что с этим делать, учитывая приведенный выше файл трассировки, но он показывает аналогичное расширение, происходящее:
SQL> var result varchar2(1000)
SQL> exec dbms_utility.expand_sql_text('select count(*) from demo natural join demo', :result)
PL/SQL procedure successfully completed.
RESULT
----------------------------------------------------------------------------------------------------------------------------------
SELECT COUNT(*) "COUNT(*)" FROM (SELECT "A2"."X" "X" FROM "WILLIAM"."DEMO" "A3","WILLIAM"."DEMO" "A2" WHERE "A2"."X"="A2"."X") "A1"
Урок: NATURAL JOIN
- зло.Все это знают.