Einleitung ANSI kompatible Join-Syntax

Transcrição

Einleitung ANSI kompatible Join-Syntax
Betrifft:
Oracle 9i New Features – SQL und PL/SQL
Autor:
Christine Hansen ([email protected])
Art der Info:
Technische Background Info – Teil 2 (April 2002)
Quelle:
Aus dem NF9i-Kurs und NF9i-Techno-Circle der Trivadis
Einleitung
Im ersten Teil haben wir von den neuen Features in Oracle 9i die SQL-Funtkionen
betrachtet. In diesem zweiten Teil werden wir uns nun mit den Neuerungen im Bereich der
ANSI kompatiblen Join-Syntax und dem Sub-Query Factoring beschäftigen.
ANSI kompatible Join-Syntax
Oracle unterstützt mit der Version 9i jetzt auch die ANSI-SQL-Syntax 99. Es stehen dabei
folgende Join-Typen zur Verfügung:
Š
Cross Join
Š
Natural Join
Š
Join mit USING-Klausel
Š
Join mit ON-Klausel
Š
Outer-Join (Left, Right und Full)
Diese Neuerungen erleichtern nicht nur den Umstieg von und zu anderen Datenbanken,
sie verbessern zusätzlich, durch die Trennung von Join- und WHERE-Bedingung, die
Lesbarkeit des Codes.
Cross Join
Der Cross Join entspricht dem kartesische Produkt von zwei oder mehr ohne JoinBedingung selektierten Tabellen.
SELECT ename, d.deptno, dname
FROM emp CROSS JOIN dept d
Es ist zu bemerken, dass eine kartesisches Produkt zweier Tabellen äußerst selten in der
Praxis benötigt wird. Durch die neue Syntax hat der Anwender den Vorteil hat, dass er auf
einen Blick erkennen kann, dass mit dem Statement wirklich ein Cross Join gemeint ist und
nicht einfach nur die WHERE-Clause vergessen wurde.
Natural Join
Der Natural-Join basiert auf den Tabellenspalten mit gleichem Namen und Datentyp. Bei
dieser Verknüpfung werden automatisch alle Spalten mit gleichem Namen und Datentyp in
die Join-Bedingung eingebunden. Die SELECT * - Syntax liefert allerdings Spalten nicht
doppelt zurück.
SELECT ename, deptno, dname
FROM emp NATURAL JOIN dept
Nicht zulässig ist die Qualifizierung von Spaltennamen mit Tabellennamen oder Aliasen:
SQL> SELECT ename, d.deptno, dname
2
FROM emp NATURAL JOIN dept d;
SELECT ename, d.deptno, dname
*
ERROR at line 1:
ORA-25155: column used in NATURAL join cannot have qualifier
Wie gewohnt kann nach der Join-Klausel eine oder mehrere WHERE-Bedingungen folgen:
SQL> SELECT ename, deptno, dname
2
FROM emp NATURAL JOIN dept
3
WHERE deptno = 10;
ENAME
DEPTNO DNAME
---------- --------- -------------CLARK
10 ACCOUNTING
KING
10 ACCOUNTING
MILLER
10 ACCOUNTING
Join mit USING-Klausel
Während beim Natural Join alle übereinstimmenden Spalten zweier Tabellen zur
Verknüpfung verwendet werden, kann über die USING-Klausel explizit eine bestimmte
Spalte für die Join-Bedingung angegeben werden. Auch hier müssen die Spalten in beiden
Tabellen den gleichen Namen und Datentyp besitzen.
SQL> SELECT ename, deptno, dname
2
FROM emp INNER JOIN dept USING(deptno)
3
WHERE job = ’SALESMAN’;
ENAME
DEPTNO DNAME
---------- --------- -------------ALLEN
30 SALES
WARD
30 SALES
MARTIN
30 SALES
TURNER
30 SALES
Join mit ON-Klausel
Join Prädikate können auch mit ON definiert werden. Dies ist z.B. dann erforderlich, wenn
die Spalten für die Join-Bedingung in den beiden Tabellen nicht den selben Namen haben.
SQL> SELECT k.marke, k.typ, d.baujahr, d.km_stand
2
FROM kfz k INNER JOIN kfz_detail d
3
ON (k.id = d.kfz_id);
MARKE
---------VW
AUDI
TYP
---------GOLF
A4
BAUJAHR
KM-STAND
-------- ---------19.03.86
289000
17.07.01
16500
Es könnten auch alle anderen Bedingungen in der ON-Klausel definiert werden:
SQL> SELECT marke, typ, baujahr, km_stand
2
FROM kfz k INNER JOIN kfz_detail d
3
ON (k.id = d.kfz_id
4
AND marke = ’JAGUAR’);
Zu empfehlen ist diese Variante aber nicht. Es ist sinnvoller die Join-Bedingung von den
einschränkenden Bedingungen (WHERE) zu trennen.
Besser wäre also folgendes Statement:
SQL> SELECT marke,
2
FROM kfz k
3
ON (k.id =
4 WHERE marke =
typ, baujahr, km_stand
INNER JOIN kfz_detail d
d.kfz_id)
’JAGUAR’;
Outer-Join (Left, Right und Full)
Neben dem Left- und Right-Outer-Join ist mit Version 9i nun auch der Full-Outer-Join
möglich. Der (+) Operator kann hier nicht mehr verwendet werden, wenn die ANSI-JoinSyntax angewendet wird.
Left-Outer-Join:
SQL> SELECT d.deptno, sum(nvl(e.sal,0)) sum_sal
2
FROM dept d LEFT OUTER JOIN emp e
3
ON d.deptno = e.deptno
4
GROUP BY d.deptno;
DEPTNO
SUM_SAL
--------- --------10
8750
20
10875
30
9400
40
0
Natürlich sind sämtliche Kombinationen von Joins möglich:
SQL> SELECT a.ename, a.mgr, b.ename manager, d.dname
2 FROM
3
emp a LEFT OUTER JOIN emp b
4
ON (a.mgr=b.empno)
5
INNER JOIN dept d
6
ON (a.deptno=d.deptno);
ENAME
MGR MANAGER
---------- ---------- ---------FORD
7566 JONES
SCOTT
7566 JONES
JAMES
7698 BLAKE
TURNER
7698 BLAKE
...
JONES
7839 KING
SMITH
7902 FORD
KING
DNAME
-------------RESEARCH
RESEARCH
SALES
SALES
RESEARCH
RESEARCH
ACCOUNTING
14 rows selected.
Full-Outer Join:
Um dieses Beispiel anschaulich darstellen zu können, wurde der Tabelle emp ein
Angestellter mit empno 8000 und job ‘Controler’ aber ohne Eintrag in department hinzugefügt.
Das Ergebnis eines Full-Outer Join von dept und emp sieht dann wie folgt aus:
SQL> SELECT d.deptno, d.dname, e.empno, e.job
2
FROM dept d FULL OUTER JOIN emp e
3
ON (d.deptno = e.deptno);
DEPTNO
---------20
30
30
20
...
20
10
40
DNAME
EMPNO JOB
-------------- ---------- --------RESEARCH
7369 CLERK
SALES
7499 SALESMAN
SALES
7521 SALESMAN
RESEARCH
7566 MANAGER
RESEARCH
ACCOUNTING
OPERATIONS
7902 ANALYST
7934 CLERK
8000 CONTROLER
16 rows selected.
Der Full-Outer-Join wird als Union-Statement optimiert:
Execution Plan
---------------------------------------------------------SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=42 Bytes=1722)
0
VIEW (Cost=4 Card=42 Bytes=1722)
1
UNION-ALL
2
HASH JOIN (OUTER) (Cost=3 Card=41 Bytes=2214)
3
TABLE ACCESS (FULL) OF 'DEPT' (Cost=1 Card=41 Bytes=902)
3
TABLE ACCESS (FULL) OF 'EMP' (Cost=1 Card=41 Bytes=1312)
2
NESTED LOOPS (ANTI) (Cost=1 Card=1 Bytes=45)
6
TABLE ACCESS (FULL) OF 'EMP' (Cost=1 Card=41 Bytes=1312)
6
INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
Sub-Query Factoring
Sub-Queries bieten eine weitere Möglichkeit Daten aus mehreren Tabellen miteinander zu
verknüpfen. Ein neues Feature in Oracle 9i ist hier die WITH-Klausel. Sie erlaubt einen
bestimmten Teil einer Sub-Query, welcher mehrfach vorkommt, einmalig zu definieren
und dann mehrfach zu verwenden. Der Optimizer entscheidet dabei, ob die benannte SubQuery als Inline View oder als Temporary Table behandelt werden soll. Das Sub- Query
Factoring gehört zum SQL-99 Standard.
WITH query_name AS (subquery) [, query_name AS (subquery) ]...
Dazu ein Beispiel das die Mitarbeiter anzeigt, deren Gehalt über dem Durchschnittsgehalt
liegt:
SQL> WITH
2
emp_sal AS (
3
SELECT deptno, ename, dname, SUM(sal) sal
4
FROM emp INNER JOIN dept USING(deptno)
5
GROUP BY ename, deptno, dname)
6 SELECT * FROM emp_sal
7
WHERE sal >
8
(SELECT avg(sal) FROM emp_sal)
9
ORDER BY deptno, ename;
DEPTNO ENAME
DNAME
SAL
---------- ---------- -------------- ----------
10
10
20
20
20
30
CLARK
KING
FORD
JONES
SCOTT
BLAKE
ACCOUNTING
ACCOUNTING
RESEARCH
RESEARCH
RESEARCH
SALES
2450
5500
3000
2975
3000
2850
Execution Plan:
Execution Plan
---------------------------------------------------SELECT STATEMENT Optimizer=CHOOSE
2
RECURSIVE EXECUTION OF 'SYS_LE_2_0'
0
TEMP TABLE TRANSFORMATION
2
SORT (ORDER BY)
3
FILTER
4
VIEW
5
TABLE ACCESS (FULL) OF 'SYS_TEMP_1_0_FD9D6615'
4
SORT (AGGREGATE)
7
VIEW
8
TABLE ACCESS (FULL) OF 'SYS_TEMP_1_0_FD9D6615''
Durch die WITH Klausel steigert sich nicht nur die Performance des SQL-Statements, auch
dessen Übersichtlichkeit wird dadurch verbessert.
Restriktionen:
Š
Š
Š
Der Queryname ist sichtbar für alle Sub-Queries und die Main-Query
Diese Klausel kann nicht verschachtelt werden. Dies bedeutet, dass es nicht möglich
ist die Sub-Query Factoring Clause als eine Sub-Query innerhalb einer anderen SubQuery Factoring Clause zu spezifizieren.
In einer Query mit gesetzten Operatoren kann der Operator nicht die Sub-Query
Factoring Clause beinhalten. Nur die FROM Subquery kann die Sub-Query Factoring
Clause enthalten.
Fazit
Oracle hat mit der Version 9i im Bereich Sub-Query Factoring einige interessante
Neuerungen, die die Performance von Statements betreffen, gebracht. Außerdem hat man
sich jetzt auch im Bereich der Joins dem ANSI 99 Standard angepasst, was eine
Erleichterung für alle Umsteiger bedeutet.
Falls Sie noch mehr über die New Features von 9i erfahren wollen, dann lesen Sie weiter in
Teil 3 in dem es um hierarchische Abfragen und CURSOR Expressions gehen wird.
Darüber hinaus würde es uns freuen, Sie in einem unserer 9i-Kurse (NF9i, AI9-A, AI9-B)
begrüßen zu dürfen.
Trivadis GmbH
Cityforum im Eichsfeld
Ferdinand-Stuttmann-Str. 13
D-65428 Rüsselsheim
Mail:
Tel:
Fax:
Internet:
[email protected]
+49 6142 210 18 0
+49 6142 210 18 29
www.trivadis.com