Złączenia wewnętrzne w bazach danych



Podobne dokumenty
Autor: Joanna Karwowska

Język SQL Złączenia. Laboratorium. Akademia Morska w Gdyni

Język SQL. Rozdział 5. Połączenia i operatory zbiorowe

Aliasy Select p.first_name, p.salary, j.job_title from employees p, jobs j where p.job_id=j.job_id;

Wykład 6. SQL praca z tabelami 3

3. Podzapytania, łączenie tabel i zapytań

Złączenie CROSS JOIN jest to tzw. złączenie krzyżowe, którego ogólna postać wygląda następująco:

Integralność danych Wersje języka SQL Klauzula SELECT i JOIN

Paweł Rajba

Systemy GIS Tworzenie zapytań w bazach danych

Wprowadzenie do projektowania i wykorzystania baz danych Relacje

Konstruowanie Baz Danych SQL UNION, INTERSECT, EXCEPT

Bazy danych. Andrzej Grzybowski. Instytut Fizyki, Uniwersytet Śląski

1 DML - zapytania, część II Grupowanie Operatory zbiorowe DML - modyfikacja 7. 3 DCL - sterowanie danymi 9.

Instytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny technologiczny Politechnika Śląska

Instytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny technologiczny Politechnika Śląska

Instytut Mechaniki i Inżynierii Obliczeniowej fb.com/groups/bazydanychmt/

PRZESTRZENNE BAZY DANYCH WYKŁAD 2

Grupowanie i funkcje agregacji

Grupowanie i funkcje agregacji. Grupowanie z użyciem rollup

Technologie baz danych

Oracle11g: Wprowadzenie do SQL

Podstawy języka SQL. standardy SQL formułowanie zapytań operacje na strukturach danych manipulowanie danymi. Bazy danych s.5-1

Marek Rakowski Zdanie SELECT wybieranie danych z wielu tabel Strona 1 z 6

Wstęp 5 Rozdział 1. Podstawy relacyjnych baz danych 9

Przestrzenne bazy danych Podstawy języka SQL

Algebra relacji. nazywamy każdy podzbiór iloczynu karteziańskiego D 1 D 2 D n.

Technologie baz danych

Złączenia pułapki i nowe możliwości

Bazy danych. Andrzej Grzybowski. Instytut Fizyki, Uniwersytet Śląski

Wykład 2. Relacyjny model danych

Bazy danych. Plan wykładu. Zależności funkcyjne. Wykład 2: Relacyjny model danych - zależności funkcyjne. Podstawy SQL.

opisuje nazwy kolumn, wyrażenia arytmetyczne, funkcje nazwy tabel lub widoków warunek (wybieranie wierszy)

D D L S Q L. Co to jest DDL SQL i jakie s jego ą podstawowe polecenia?

Zasady transformacji modelu DOZ do projektu tabel bazy danych

Wprowadzenie do języka SQL

Wykład XII. optymalizacja w relacyjnych bazach danych

Wykład 8. SQL praca z tabelami 5

SQL (ang. Structured Query Language)

Bazy danych. Bazy danych. Podstawy języka SQL. Dr inż. Paweł Kasprowski.

RBD Relacyjne Bazy Danych

Przykłady najlepiej wykonywać od razu na bazie i eksperymentować z nimi.

SQL Structured Query Language

Podzapytania. Rozdział 5. Podzapytania. Podzapytania wyznaczające wiele krotek (1) Podzapytania wyznaczające jedną krotkę

Rozpatrzymy bardzo uproszczoną bazę danych o schemacie

Laboratorium nr 8. Temat: Podstawy języka zapytań SQL (część 2)

BAZY DANYCH LABORATORIUM. Studia niestacjonarne I stopnia

77. Modelowanie bazy danych rodzaje połączeń relacyjnych, pojęcie klucza obcego.

Bazy danych. Plan wykładu. Diagramy ER. Podstawy modeli relacyjnych. Podstawy modeli relacyjnych. Podstawy modeli relacyjnych

Wykład 7 Implementacja języka SQL w systemach baz danych Oracle sortowanie, funkcje agregujące i podzapytania.

Temat : SBQL 1 obiektowy język zapytań.

PRZEWODNIK PO PRZEDMIOCIE

Język SQL. Rozdział 2. Proste zapytania

SQL - Structured Query Language -strukturalny język zapytań SQL SQL SQL SQL

Podzapytania. Rozdział 5. Podzapytania. Podzapytania wyznaczające wiele krotek (1) Podzapytania wyznaczające jedną krotkę

Optymalizacja poleceń SQL Metody dostępu do danych

Alicja Marszałek Różne rodzaje baz danych

SQL SERVER 2012 i nie tylko:

Język SQL. Rozdział 9. Język definiowania danych DDL, część 2.

Program szkoleniowy Efektywni50+ Moduł IV Podstawy relacyjnych baz danych i język SQL

Laboratorium Bazy danych SQL 2

Indeksowanie w bazach danych

Bazy Danych. SQL Podstawy języka III: powtórzenie. Krzysztof Regulski WIMiIP, KISiM, B5, pok. 408

Wstęp do SQL. copyright: KGiIS WGGiOŚ AGH

Złaczenia tablic: FROM, WHERE, JOIN

PHP: bazy danych, SQL, AJAX i JSON

Bazy danych. Dr inż. Paweł Kasprowski

Laboratorium nr 5. Temat: Funkcje agregujące, klauzule GROUP BY, HAVING

SIECI KOMPUTEROWE I BAZY DANYCH

Cel przedmiotu. Wymagania wstępne w zakresie wiedzy, umiejętności i innych kompetencji 1 Język angielski 2 Inżynieria oprogramowania

Bazy danych Ćwiczenia projektowe

Wykład :45 BD-1 W_3

Bazy danych - wykład wstępny

Podstawowym zadaniem, które realizuje

SQL w 24 godziny / Ryan Stephens, Arie D. Jones, Ron Plew. Warszawa, cop Spis treści

CREATE DATABASE ksiegarnia_internetowa DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Model relacyjny. Wykład II

Język SQL. instrukcja laboratoryjna. Politechnika Śląska Instytut Informatyki. laboratorium Bazy Danych

Microsoft SQL Server Podstawy T-SQL

Administracja i programowanie pod Microsoft SQL Server 2000

Laboratorium nr 10. Temat: Połączenia relacji

Dane wejściowe. Oracle Designer Generowanie bazy danych. Wynik. Przebieg procesu

SIECI KOMPUTEROWE I BAZY DANYCH

Bazy danych Wykład zerowy. P. F. Góra

Projekt jest finansowany ze środków Unii Europejskiej, Europejskiego Funduszu Społecznego i budŝetu państwa. Studia Podyplomowe dla Nauczycieli

SQL Server i T-SQL w mgnieniu oka : opanuj język zapytań w 10 minut dziennie / Ben Forta. Gliwice, Spis treści

Szkolenie autoryzowane. MS Tworzenie zapytań do Microsoft SQL Server Strona szkolenia Terminy szkolenia Rejestracja na szkolenie Promocje

1 Wstęp do modelu relacyjnego

3 Przygotowali: mgr inż. Barbara Łukawska, mgr inż. Maciej Lasota

Struktura drzewa w MySQL. Michał Tyszczenko

XQTav - reprezentacja diagramów przepływu prac w formacie SCUFL przy pomocy XQuery

T-SQL dla każdego / Alison Balter. Gliwice, cop Spis treści. O autorce 11. Dedykacja 12. Podziękowania 12. Wstęp 15

Model relacyjny. Wykład II

Relacyjne bazy danych. Podstawy SQL

1 Podstawy c++ w pigułce.

Bazy danych Algebra relacji Wykład dla studentów matematyki

Wprowadzenie do baz danych

Wprowadzenie do baz danych

Uzupełnij pola tabeli zgodnie z przykładem poniżej,

Transkrypt:

Rozdział 23 Złączenia wewnętrzne w bazach danych Streszczenie. W rozdziale pokazano problemy związane ze stosowaniem złączeń (ang. joins) tabel w modelu relacyjnym. Pozornie proste złączenia (kanon pracy z modelem relacyjnym) będące elementem zapytania SQL mogą być źródłem istotnych błędów w przypadku stosowania różnych składni języka SQL dostępnych w danym systemie bazodanowym. Zasygnalizowane problemy zilustrowano przykładami zapytań budowanych w wybranym systemie komercyjnym (Oracle), które dopuszczają stosowanie zarówno firmowej składni (nie w pełni zgodnej z normą ANSI) jak i składni zdefiniowanej w normie ANSI. W rozdziale omówiono jedynie problemy dotyczące złączeń wewnętrznych (ang. Inner Joins). Drugi podstawowy typ złączeń (złączenia zewnętrzne; ang. Outer Joins) oraz tzw. złączenia hierarchiczne (ang. Self Joins) omówiono w rozdziale Złączenia zewnętrze i hierarchiczne w bazach danych. 1 Wstęp Jedną z najważniejszych cech języka SQL jest możliwość pobierania danych z więcej niż jednej relacji (tabeli). W praktyce bowiem trudno sobie wyobrazić rzeczywistą aplikację operującą na jednej tylko tabeli. W konsekwencji bezbłędna i wydajna obsługa złączeń tabel z poziomu języka SQL nabiera pierwszorzędnego znaczenia. Niniejszy rozdział poświęcony jest omówieniu wybranych aspektów złączeń w relacyjnej bazie danych Oracle. W dostępnej literaturze stosunkowo mało miejsc poświęca się na wnikliwe omówienie zagadnień związanych ze złączeniami w relacyjnych bazach danych. Problem ten jest tak stary jak teoria (i praktyka) tych baz i wydawałoby się, że na ten temat wszystko już zostało powiedziane i wszystko jest jasne i klarowne. Nie jest to jednak prawdą, gdyż producenci systemów baz danych nadal w swoich nowych wersjach produktów wprowadzają różnego rodzaju zmiany i uzupełnienia. Znamiennym przykładem jest tutaj firma Oracle, która dopiero od wersji 9i swojej bazy zdecydowała się na pełną implementację złączeń w stylu Jarosław Gramacki, Artur Gramacki: Uniwersytet Zielonogórski, Instytut Informatyki i Elektroniki, ul. Podgórna 50, 65-246, Zielona Góra e-mail: {j.gramacki, A.Gramacki}@iie.uz.zgora.pl

J. Gramacki, A. Gramacki zalecanym przez normę ANSI. Nadal jednak pozostawiono wsparcie dla dotychczasowej starej składni (przynajmniej do wersji 10g, która w chwili pisania pracy jest ostatnim wydaniem systemu). Pokazano, że równoległe istnienie obu składni wprowadza pewne problemy, zwłaszcza, że obie składnie nie są ze sobą w pełni zgodne. Szczególną uwagę zwrócono na pokazanie wspólnych cech oraz różnic obu dostępnych składni oraz różnych problemów i potencjalnych błędów, które mogą się w związku z tym ujawnić. Omówiono zagadnienia dotyczące złączeń wewnętrznych (ang. Inner Joins). Drugi podstawowy typ złączeń (złączenia zewnętrzne; ang. Outer Joins) oraz tzw. złączenia hierarchiczne (ang. Self Joins) będące pewnym szczególnym przepadkiem złączeń wewnętrznych omówiono w rozdziale Złączenia zewnętrze i hierarchiczne w bazach danych. 2 Model danych Przy opisie jakichkolwiek zagadnień dotyczących języka SQL konieczny jest odpowiedni, adekwatny do opisywanych problemów, schemat tabel relacyjnych wraz z ich powiązaniami. Na rys. 1 przedstawiono wykorzystywany w pracy model relacyjny 1. Jest to znany większości użytkowników systemu Oracle model o nazwie Human Resource (HR) [1] uzupełniony o dwie dodatkowe tabele: Sports oraz Sport_enrollment. Opisują one prowadzone w firmie ligi sportowe oraz pracowników, którzy zapisali się na dane rozgrywki. Poniżej pokazano dane umieszczone w tych tabelach: Tablela Sports DISCIPLINE SEASON ------------------- ---------- football spring05 football winter05 hockey autumn05 hockey spring05 tennis spring05 tennis spring06 tennis summer05 volleyball spring05 volleyball summer05 volleyball winter05 Tabela Sports_enrollment DISCIPLINE SEASON EMPLOYEE_ID ------------ ---------- ----------- hockey spring05 100 tennis summer05 200 tennis summer06 105 Potrójny klucz primary (na wszystkich kolumnach tabeli Sport_enrollment) utworzono, aby bezkosztowo uniemożliwić wielokrotne zapisanie się tego samego pracownika na te same rozgrywki. Wymieńmy kilka cech schematu, które będą istotne w pracy: Kolumna Employees.manager_ID dopuszcza wartość NULL. Nie każdy więc zarejestrowany w bazie pracownik musi mieć swojego podwładnego. Kolumna Employees.department_ID dopuszcza wartość NULL. Nie każdy więc zarejestrowany w bazie pracownik musi być przypisany do konkretnego działu firmy. Kolumna Departments.manager_ID dopuszcza wartość NULL. Nie każdy więc zarejestrowany w bazie dział firmy musi mieć swojego kierownika. Wygodna na etapie modelowania, ale sprawiająca trudności w użyciu i podatna na błędy, relacja wewnętrzna Employees.employee_ID -> Employees.manager_ID. 1 W pracy wszystkie nazwy tabel pisane są małymi literami + pierwsza litera duża (np. Departments), nazwy kolumn w całości małymi literami (np. title), aliasy dla kolumn to jedna bądź dwie duże litery (np. J, SE). 226

Złączenia wewnętrzne w bazach danych W tabeli Sport_enrollment pracownik może zapisać się do sekcji sportowej, która akurat nie jest prowadzona w danym sezonie (np. sekcja tenisa jest oferowana tylko w sezonie letnim 2005). Rys. 1. Model relacyjny HR wykorzystywany w pracy Część z wymienionych właściwości (pierwsze trzy) może być efektem celowo przyjętych założeń i z formalnego punktu widzenia nie stanowi to błędu. Właściwość czwartą można by zastąpić odpowiednią strukturą typu master-detail (mniej podatna na błędy w zapytaniach SQL), jednak wtedy należałoby z góry ustalić ilość poziomów podległości pracowników. Właściwość piąta jest wynikiem pewnego niedbalstwa projektanta bazy (żeby nie powiedzieć szkolnego błędu). Bez problemu można było utworzyć odpowiednie ograniczenie, np. poleceniem: ALTER TABLE Sport_enrollment ADD CONSTRAINT xxx_fk FOREIGN KEY (discipline, season_id) REFERENCES Sports (discipline, season_id); Ograniczenie to widać co prawda na rys. 1. ale na potrzeby artykułu dezaktywowano je. Abstrahując jednak od powyższej dyskusji, w praktyce często przychodzi nam pracować na modelu takim, jaki jest (nie mamy możliwości zmiany modelu). Dużego znaczenia nabiera wtedy poprawne konstruowanie zapytań opartych na danym modelu. 227

J. Gramacki, A. Gramacki 3 Złączenia w systemie Oracle Złączenia zajmują ważne miejsce w każdej bazie relacyjnej i są to jej bardzo newralgiczne elementy. Dokumentacja systemu Oracle poświęca im jednak stosunkowo niewiele miejsca, dodatkowo prawie zupełnie nie zwracając uwagi na różne związane z nimi niuanse (prezentowane tam przykłady są maksymalnie uproszczone). Ponadto w oryginalnej dokumentacji systemu Oracle pojawia się aż siedem pojęć, w których używana jest fraza join 2, zestawiono je poniżej. W nawiasach podano również inne, pojawiające się w różnych publikacjach nazwy, które jednak nie pojawiają się w dokumentacji Oracle. W tabeli 1 krótko opisano każde ze złączeń: Natural Joins, Equijoins, Self Joins, Cartesian Products, Inner Joins (Simple Joins), Outer Joins, Antijoins, Semijoins, (Theta Joins) Najogólniej mówiąc wszelkie złączenia można podzielić na dwie podstawowe grupy: wewnętrznych (ang. Inner Joins) oraz zewnętrzne (ang. Outer Joins).Wszelkie inne bardziej szczegółowe podziały dotyczą pewnych zawężonych obszarów zastosowania. Mimo tego w sumie bardzo prostego i oczywistego podziału dokumentacja firmy Oracle dopiero od wersji 10g w sposób wyraźny wprowadza ten podział w diagramach syntaktycznych dla polecenie. Pojawiają się tam oddzielne bloki o nazwach [4, str. 19-8]: inner_cross_join_clause, outer_join_clause, outer_join_type, podczas gdy w dokumentacji do wersji 9i są tylko bloki o ogólnych nazwach [5, str. 18-8]: joined_table, join_type, które zawierają w sobie elementy zarówno złączeń zewnętrznych jak i wewnętrznych. Z analizy zawartości tabeli 1 wynika, że istnienie przynajmniej kilku z podanych tam pojęć jest dyskusyjne, gdyż służą one do opisu stosunkowo wąskiego zbioru zapytań. Z drugiej strony niektóre nazwy opisują bardzo ogólne właściwości, typowe raczej dla całego podejścia relacyjnego. Dla każdego wymienionego typu złączenia w dalszej części tego Rozdziału (oraz w Rozdziale Złączenia zewnętrze i hierarchiczne w bazach danych ) podano odpowiednio dobrany, rzeczywisty przykład zapytania. Tabela 1. Różne używane pojęcia związane ze złączeniami relacyjnymi Nazwa Inner Joins Opis Złączenie dwóch lub więcej tabel, które zwraca w wyniku tylko wiersze 2 Wszędzie użyto pisowni zgodnej z używaną w oryginalnej dokumentacji firmy Oracle. 228

Złączenia wewnętrzne w bazach danych (Simple Joins) pasujące do warunku złączenia. Outer Joins Rozszerzenie funkcjonalności oferowanej przez złączenie typu Inner Joins. Do wyniku, który generowałby Inner Join dodawane są wiersze niepasujące. Rozróżnia się złączenia zewnętrzne lewostronne (Left Outer Joins), prawostronne (Right Outer Joins), pełne (Full Outer Joins). Natural Joins Złączenie dwóch lub więcej tabel poprzez kolumny o tych samych nazwach. Jest to szczególny przypadek złączeń Inner Joins. Equijoins Dotyczy złączenia opisanego operatorem porównania. Nie wspomina się o żadnych dodatkowych zagadnieniach/założeniach szczegółowych. Może to więc być zarówno złączenie Outer Joins jaki i Inner Joins. Self Joins Dotyczy złączenia w obrębie jednej tabeli. Tabela ta musi więc dwa razy pojawić się w klauzuli (z reguły z dwoma różnymi aliasami). Struktura taka zwykle zawiera dane mające postać struktury hierarchicznej (podległościowej). Jest to również szczególny przypadek złączeń Inner Joins. Cartesian Products Wynik złączenia dwóch lub więcej tabel, dla których nie podano warunku złączenia. Każdy wiersz z jednej tabeli złączony zostanie z każdym wierszem drugiej tabeli. Poza rzadkimi przypadkami szczególnymi, jest to z reguły wynik błędu w zapytaniu. Jest to również szczególny przypadek złączeń Inner Joins. Antijoins Złączenie zwracające wiersze, które NIE pasują do podanego warunku. Semijoins Złączenie z warunkiem EXISTS. Duplikaty zostają usunięte. Theta Joins Złączenie nierównościowe. Złączenie dwóch relacji dla kryterium złączenia innym niż równość. 4 Przykłady zapytań W pozostałej części rozdziału zamieszczono pewną liczbę przykładów ilustrujących wybrane zagadnienia dotyczące złączeń relacyjnych oraz krótkie komentarze tychże przykładów. Część przykładów zaczerpnięto z prac [2], [3], dostosowując je do używanego w rozdziale schematu relacyjnego. Przykłady starano się dobrać tak, aby pojawiały się w nich pewne problemy. Tam, gdzie to tylko było możliwe, zastosowano nową (dostępną począwszy od wersji 9i bazy Oracle) składnię złączeń zdefiniowaną w standardzie SQL/99 3. Należy jednak zaznaczyć, że nowa składnia NIE wprowadza żadnej nowej funkcjonalności, której nie było w systemie do tej pory. Czyni jednak zapytania bardziej zgodnymi z normą ANSI- SQL 4. Ponadto nowa składnia w wielu przypadkach jest bardziej samodokumentująca się i łatwiejsza w czytaniu (zwłaszcza, gdy zapytanie złącza wiele tabel np. kilkanaście- i wówczas nie zawsze łatwo jest się zorientować, co zapytanie dokładnie robi). 3 W wielu publikacjach pojawia się taka właśnie nazwa. Należy ją jednak traktować jako umowny skrót. Równie dobry skrót byłby SQL/2003 Poprawna nazwa normy to: ANSI/ISO/IEC 9075- [tu numer od 1 do 14]:2003 4 Norma dostępna na stronie http://webstore.ansi.org/ansidocstore/default.asp. 229

J. Gramacki, A. Gramacki 4.1 Złączenia naturalne (ang. Natural Joins) Złączenia naturalne dotyczą szczególnego przypadku, gdy w łączonych tabelach kolumny kluczowe mają te same nazwy. W składni ANSI złączenie to, choć merytorycznie bardzo proste, podatne jest na niespodziewane błędy. Przykład 1 R.region_id, R.region_name, C.country_id, C.country_name Countries C, Regions R R.region_id = C.region_id AND LOWER(R.region_name) LIKE %europe%'; region_id, R.region_name, C.country_id, C.country_name Regions R NATURAL JOIN Countries C LOWER(R.region_name) LIKE '%europe%'; składnia ANSI umożliwia rozdzielenie warunków złączenia od innych warunków w klauzuli tu ograniczających wyniki do regionów europejskich. W dotychczasowej składni oba warunki musiały występować w klauzuli i dla złożonych zapytań trudno było odróżnić je od siebie. dla składni ANSI, często w takim przypadku pojawia się błąd: ORA-25155: column used in NATURAL join cannot have qualifier. Nie jest możliwe więc używanie prefiksów tabel dla łączonych kolumn. Stąd zamiast R.region_id musi być region_id (nawet pomimo istnienia aliasów dla tabel). wydaje się, że używanie klauzuli NATURAL JOIN, jest podatne na błędy. Łatwo bowiem o (trudny do wykrycia) błąd, który wystąpi po dodaniu do schematu kolumny, która przypadkowo będzie nazywała się tak samo, jak kolumna w zapytaniu używającym NATURAL JOIN. W tym przypadku system użyje w złączeniu wszystkich kolumn o pasujących nazwach. System Oracle implementuje tą składnię, ale wynika to chyba raczej z potrzeby zapewnienia zgodności ze standardem ANSI, którego użyteczność w przypadku NATURAL JOIN jest jednak dyskusyjna. zabronione jest używanie innych klauzul (na przykład opisywanej niżej klauzuli ON) z klauzulą NATURAL JOIN. w przypadku naturalnego złączenia więcej niż dwóch tabel należy używać nawiasów. Bez nich w niektórych systemach to samo zapytanie może być inaczej obsługiwane (system Oracle stosuję łączność lewostronną): Wyrażenie a NATURAL JOIN b JOIN c ON b.c1 = c.c1 bez nawiasów może być interpretowane na dwa sposoby a NATURAL JOIN (b JOIN c ON b.c1 = c.c1) lub (a NATURAL JOIN b) JOIN c ON b.c1 = c.c1 Pomiędzy łączonymi tabelami może oczywiście istnieć więcej niż tylko jedno złączenie. Określeniu, podług których kolumn ma następować złączenie służy w takich przypadkach klauzula USING. Użycie jej wymaga jednak ostrożności. 230

Przykład 2 D.department_name, E.last_name ' ' e.first_name Name, E.hire_date Departments D, Employees E D.department_id = E.department_id AND E.job_id = 'IT_PROG'; Złączenia wewnętrzne w bazach danych D.department_name, E.last_name ' ' e.first_name Name, E.hire_date Departments D JOIN Employees E USING (department_id) E.job_id = 'IT_PROG'; W złożonych zapytaniach istotnym problemem jest rozdzielenie warunków złączeń wynikających z postaci relacyjnej schematu od pozostałych warunków ograniczających ilość zwracanych wyników. (nie-ansi) nie posiada żadnych formalnych mechanizmów dyscyplinujących programistę. Może on dowolnie wymieszać po jeśli w zapytaniu w notacji ANSI zamiast: Departments D JOIN Employees E USING (department_id) zapiszemy: Departments D NATURAL JOIN Employees warunków, to otrzymamy zły wynik. W powyższym przykładzie natura zagrożenia jest inna niż zagrożenie sygnalizowane w przykładzie 1. Tabele Employees oraz Departments łączą DWIE relacje (department_id = department_id oraz department_id = department_id) i dlatego należy doprecyzować, o które złączenie chodzi. Umożliwia to klauzula USING. klauzuli USING można używać tylko wówczas, gdy odpowiednie kolumny obu tabel mają takie same nazwy. Dotychczasowa składnia jest wolna od takich zagrożeń, gdyż warunek złączenia podany jest jawnie. Mówimy tu jednak ciągle o złączeniach naturalnych, które ze swej natury wymagają kolumn o identycznych nazwach. klauzula USING subtelnie psuje jednak semantykę zapytania. Błędem zakończy się np. D.department_name, D.department_ID, E.department_ID,... gdyż zapytanie zwróci: ORA-25154 -column part of USING clause cannot have qualifier. W dotychczasowej składni błąd ten nie wystąpi. w klauzuli USING nie ma ograniczenia na ilość kolumn w niej wymienianych. Zapytanie jak poniżej jest jak najbardziej poprawne: discipline, -- Błąd, gdy S.discipline - patrz opis wyżej season_id, SE.employee_ID Sports S INNER JOIN Sport_enrollment SE USING (discipline, season_id); zamiast klauzuli JOIN można użyć dłuższej, ale bardziej opisowej wersji INNER JO- IN, która podkreśla, że chodzi o złączenie wewnętrzne. Oracle nie wymusza jednak tego. Podobnie jest ze słowem kluczowym OUTER w złączeniach zewnętrznych. Ta opcjonalność w użyciu słów INNER oraz OUTER jest nieco dziwna. W praktyce nic to nie daje a tylko wprowadza niepotrzebną niekonsekwencję. Należy więc przypuszczać, że wśród programistów zapanuje duża dowolność w jego stosowaniu. klauzula USING istotnie zwiększa czytelność zapytania. 4.2 Złączenia wewnętrzne (ang. Inner Joins) 231

J. Gramacki, A. Gramacki szczególne warunki w klauzuli, co często czyni zapytanie trudnym do czytania. Klauzula INNER JOIN jest więc pod tym względem krokiem w dobrym kierunku. Przykład 3a D.department_name, E.last_name ' ' E.first_name Name, SE.discipline, SE.season_ID Departments D, Employees E, Sport_enrollment SE D.department_id = E.department_id AND E.employee_ID=SE.employee_ID AND E.job_id = 'IT_PROG'; 232 D.department_name, E.last_name ' ' E.first_name Name, SE.discipline, SE.season_ID Departments D INNER JOIN Employees E ON (D.department_id =E.department_id) INNER JOIN Sport_enrollment SE ON (E.employee_ID=SE.employee_ID) E.job_id = 'IT_PROG'; sens zastosowania klauzuli ON sprowadza się jedynie do (eleganckiego) rozdzielenia warunków złączenia od innych warunków logicznych W tradycyjnej składni wszystkie warunki występowały razem w ramach klauzuli. Przykład 3b S.discipline, S.season_ID, E.employee_ID, -- alias konieczny E.last_name Sports S, Sport_enrollment SE, Employees E S.discipline = SE.discipline AND S.season_id = SE.season_id AND E.employee_ID = SE.employee_ID discipline, season_id, employee_id, -- teraz alias -- zabroniony E.last_name Sports S INNER JOIN Sport_enrollment SE USING (discipline, season_id) INNER JOIN Employees E USING (employee_id) złączenia wielokrotne są możliwe. INNER JOIN uwypukla kolejność złączeń, Oracle domyślnie wykonuje złączenia w kierunku od lewej do prawej. Najpierw złączenie Sports z Sport_enrollment, a następnie wynik tego złączenia z Employees. Można to jednak zmienić stosując w odpowiednim miejscu nawiasy. Przykład 3c S.discipline, S.season_ID, SE.employee_ID Sports S, Sport_enrollment SE S.discipline = SE.discipline AND -- wersja z USING discipline, -- tu alias zabroniony season_id, -- tu alias zabroniony SE.employee_ID Sports S INNER JOIN Sport_enrollment SE USING (discipline, season_id)

S.season_id = SE.season_id; Złączenia wewnętrzne w bazach danych -- wersja z ON S.discipline, -- tu alias obowiązkowy S.season_ID, -- tu alias obowiązkowy SE.employee_ID Sports S INNER JOIN Sport_enrollment SE ON S.discipline = SE.discipline AND S.season_id = SE.season_id; wersje z USING i ON są w tym przypadku równoważne, gdyż odpowiednie kolumny łączonych tabel mają takie same nazwy. W praktyce nie zawsze ma to miejsce, klauzula ON jest mniej czytelna od klauzuli USING. Mając wybór lepiej zastosować USING, gdyż jest ona krótsza i bardziej czytelna, w klauzuli ON może pojawić się dowolne wyrażenie logiczne. Niemniej w praktyce większość zapytań to zapytania równościowe (Equijoins), w których porównujemy odpowiednie kolumny dwóch (lub więcej) tabel, zwracamy uwagę na obowiązkowość / niedozwoloność stosowania aliasów przy nazwach kolumn. Przejście między obu składniami wymaga więc dodania / usunięcia odpowiednich aliasów. Jest to czynność czysto mechaniczna, jednak często o tym po prostu zapominamy. 4.3 Złączenia nierównościowe (ang. Theta Joins) Złączenia nierównościowe, zdecydowanie rzadziej stosowane w praktyce, niosą ze sobą niebezpieczeństwo istotnego obniżenia wydajności systemu. Cecha ta nie jest jednak widoczna dla niewprawnego programisty. Przykład 4 E.job_id, J.job_title, E.first_name ' ' E.last_name Name, J.min_salary '--' J.max_salary "Przedział", E.salary Employees E, Jobs J E.salary BETWEEN J.min_salary AND J.max_salary AND E.last_name LIKE 'Abel' ORDER BY E.last_name; E.job_id, J.job_title, E.first_name ' ' E.last_name Name, J.min_salary '--' J.max_salary "Przedział", E.salary Employees E INNER JOIN Jobs J ON (E.salary BETWEEN J.min_salary AND J.max_salary) E.last_name LIKE 'Abel' ORDER BY E.last_name; przykład pokazuje złączenie nierównościowe (ang. Theta Joins). Zdecydowanie rzadziej używane niż złączenia równościowe, w powyższym przykładzie wyświetlono listę pracowników oraz, na bazie tabeli Jobs, sprawdzono, czy zarobki poszczególnych pracowników mieszczą się w widełkach. Można przykładowo zauważyć, że pracownik o nazwisku Abel, pracujący na stanowisku Sales Representative zarabia kwotę 11 000, która to kwota mieści się w przedziale dla pięciu innych stanowisk, 233

J. Gramacki, A. Gramacki złączenie jest bardzo pracochłonne do wykonania. Wymaga najpierw utworzenia iloczynu kartezjańskiego a następnie wybraniu z niego wierszy, dla których zadany warunek jest spełniony: -- Wynik zapytania JOB_ID JOB_TITLE NAME Przedział SALARY ------ --------------------- ---------- -------------- ---------- SA_REP Finance Manager Ellen Abel 8200 -- 16000 11000,00 SA_REP Accounting Manager Ellen Abel 8200 -- 16000 11000,00 SA_REP Sales Representative Ellen Abel 6000 -- 12000 11000,00 SA_REP Sales Manager Ellen Abel 10000-20000 11000,00 SA_REP Marketing Manager Ellen Abel 9000 -- 15000 11000,00 SA_REP Purchasing Manager Ellen Abel 8000 -- 15000 11000,00 4.4 Złączenia wykluczające (ang. Antijoins) Zdarzają się sytuacje, w których intuicyjnie gorsza wersja zapytania jest / może być wydajnościowo lepsza w innej jego postaci. Właściwy wybór uzależniony jest od umiejętności dostrzegania takich przypadków w pisanych zapytaniach. Przykład 5 -- Antijoins E.job_id, E.first_name ' ' E.last_name Name, E.salary Employees E department_id NOT IN ( department_id Departments location_id BETWEEN 1700 AND 2700); -- Equijoins E.job_id, E.first_name ' ' E.last_name Name, E.salary Departments D, Employees E D.department_id=E.department_id AND D.location_ID NOT BETWEEN 1700 AND 2700; -- Antijoins Nie dotyczy -- Equijoins E.job_id, E.first_name ' ' E.last_name Name, E.salary Departments D INNER JOIN Employees E USING (department_id) D.location_ID NOT BETWEEN 1700 AND 2700; Plany wykonania -- Antijoins STATEMENT FILTER TABLE ACCESS FULL EMPLOYEES TABLE ACCESS BY INDEX ROWID DEPARTMENTS INDEX RANGE SCAN DEPT_LOCATION_IX -- Equijoins STATEMENT 234

CONCATENATION TABLE ACCESS BY INDEX ROWID EMPLOYEES NESTED LOOPS TABLE ACCESS BY INDEX ROWID DEPARTMENTS INDEX RANGE SCAN DEPT_LOCATION_IX INDEX RANGE SCAN EMP_DEPARTMENT_IX TABLE ACCESS BY INDEX ROWID EMPLOYEES NESTED LOOPS TABLE ACCESS BY INDEX ROWID DEPARTMENTS INDEX RANGE SCAN DEPT_LOCATION_IX INDEX RANGE SCAN EMP_DEPARTMENT_IX Złączenia wewnętrzne w bazach danych przykład pokazuje zapytanie, w którym interesuje nas BRAK zachodzenia danej relacji (złączenie Antijoins). Pokazano pracowników pracujących na wydziałach zlokalizowanych w wybranych lokalizacjach (poprzez negacje pozostałych), dla Antijoins występuje podzapytanie. Dyskusja nad użyciem składni ANSI jest wiec dla tego przykładu bezprzedmiotowa, ten sam wynik osiągnąć można stosując zwykłe złączenia równościowe dwóch tabel, plan wykonania zapytania Equijoins w stosunku do planu zapytania Antijoins będzie jednak bardziej złożony. W planie dla Antijoins występuje jednakże operacja TABLE ACCESS FULL. W konkurencyjnym planie wszędzie korzystamy z indeksów, decyzję, czy użyć złączenia Antijoins, czy zwykłego równościowego Equijoins powinna poprzedzić analiza planu zapytania pod kątem ewentualnych korzyści i/lub strat. 4.5 Iloczyn kartezjański (ang. Cartesian Product) Przykład 6 D.department_name, L.city, departments D, locations L; D.department_name, L.city departments D CROSS JOIN locations L; iloczyn kartezjański najczęściej pojawia się jako niezamierzony wynik (brak jakiegoś koniecznego złączenia). Nowa składnia wymaga jawnego wskazania, że intencją programisty był iloczyn kartezjański, ponieważ jednak tradycyjna składnia ciągle jest (i pewnie będzie) obsługiwana przez bazę Oracle, więc praktyczna użyteczność CROSS JOIN w sensie eliminacji błędów jest bardzo dyskusyjna. Porządkuje jedynie sprawę pod katem terminologicznym. 5 Wnioski W rozdziale pokazano, że z pozoru proste zagadnienia jakim są złączenia relacyjne, po uwzględnieniu wielu zagadnień szczegółowych, stają się podatne na błędy. Jeśli dodatkowo uwzględni się możliwość korzystania z nowej składni ANSI, ewentualnych problemów przybędzie. SQL nie zawsze jest w 100% odpowiednikiem składni dotychczasowej. Warto o tym zawsze pamiętać. Na wyniki zapytań ze złączeniami istotnie wpływać mogą również przyjęte założenia projektowe odzwierciedlone w modelu relacyjnym. 235

J. Gramacki, A. Gramacki Literatura 1. Oracle Database, Sample Schemas, 10g Release 1 (10.1), Part No. B10771-01 2. Gennick J.: An Incremental Approach to Developing SQL Queries. Oracle Magazine, July/August 2000, Volume XIV, Issue 4 3. Czuprynski J.: Getting ANSI About Joins, dostępne na otn.oracle.com 4. Oracle Database SQL Reference 10g Release 1 (10.1) Part Number B10759-01 5. Oracle Database SQL Reference 9i Release 2 (9.2) Part Number A96540-02 6. Gramacki J., Gramacki A.: Połączenia - pułapki i nowe możliwości, Systemy informatyczne. Projektowanie, implementowanie, eksploatowanie - PLOUG : X Konferencja użytkowników i deweloperów ORACLE. Kościelisko, Polska, 2004, Warszawa, Stowarzyszenie Polskiej Grupy Użytkowników Systemu Oracle, 2004, strony 259-277 236