W PostgreSQL tabela może dziedziczyć również z kilku tabel. Struktura dziedziczenia nie może jednak zawierać cykli.
W PostgreSQL można definiować typy w sposób zbliżony do SQL3. Definicja ma postać:
CREATE TYPE typ AS OBJECT ( lista atrybutów i metod );
Używając jej możemy zdefiniować typ dla punktów:
CREATE TYPE punkt_t AS OBJECT ( x NUMERIC, y NUMERIC );
Po zdefiniowaniu typu obiektowego używa się podobnie jak typów standardowych, np. możemy teraz zdefiniować typ dla odcinków:
CREATE TYPE odcinek_t AS OBJECT ( początek punkt_t, koniec punkt_t );
Możemy teraz utworzyć tabelę zawierającą odcinki wraz z ich identyfikatorami (ID):
CREATE TABLE Odcinki ( ID INT, odcinek odcinek_t );
Typy usuwamy poleceniem DROP:
DROP TYPE odcinek_t;
Przed usunięciem typu trzeba jednak oczywiście usunąć wszystkie tabele oraz inne typy, które używają danego typu a type, więc powyższe polecenie zakończy się niepowodzeniem. Trzeba najpierw usunąć tabelę Odcinki.
Typów zdefiniowanych można również używać bezpośrednio de definiowania tabel (odpowiednik ,,rowtype'' z SQL3). W poleceniu CREATE TABLE można zastąpić listę kolumn słowem kluczowym OF i nazwą typu, np.
CREATE TABLE Odcinki OF odcinek_t;
PostgreSQL dla każdego definiowanego typu tworzy automatycznie funkcję konstruktora o tej samej nazwie. Obiekt typu punkt_t tworzy się wywołując funkcję odcinek_t od (podanej w nawiasach) listy wartości atrybutów, np.
INSERT INTO Odcinki VALUES(27, odcinek_t(punkt_t(0.0, 0.0), punkt_t(3.0, 4.0)));
Dostęp do składowych obiektu uzyskuje się używając notacji kropkowej. Jeśli O jest pewnym obiektem typu T, którego jedną ze składowych (atrybutów lub metod) jest A, to O.A odnosi się do tej składowej w obiekcie O.
Możemy wyszukać współrzędne początków owszystkich odcinków
SELECT o.odcinek.początek.x, o.odcinek.początek.y FROM Odcinki o;
Użycie aliasu jest w takich sytuacjach obowiązkowe. Zapytanie
SELECT o.odcinek.koniec FROM Odcinki o;
wyszuka końce wszystkich odcinków (wypisując je ewentualnie jako wywołania konstruktora.
Dla typu t wyrażenie REF t oznacza jego typ referencyjny (,,ID obiektu''). Można go używać w definicjach kolumn:
CREATE TABLE Odcinki ( początek REF punkt_t, koniec REF punkt_t );
Używając takiego typu trzeba pamiętać o pewnych ograniczeniach. Konkretne referencje muszą odnosić się do wierszy tabeli podanego typu. Na przykład dla tabeli
CREATE TABLE Punkty OF punkt_t;
możemy umieścić w tabeli Odcinki referencje do wierszy z tej tabeli:
INSERT INTO Odcinki SELECT REF(pp), REF(qq) FROM Points pp, Points qq WHERE pp.x < qq.x;
Referencje nie mogą natomiast odnosić się do obiektów występujących w kolumnach innych tabel, ani nie mogą być tworzone ad hoc (np. umieszczając w poleceniu INSERT klauzulę VALUES(REF(puntk_t(1,2)), REF(punkt_t(3,4)))).
Przechodzenie po referencji zapisuje się używając notacji kropkowej, np. poniższe zapytanie podaje współrzędne x początków i końców wszystkich odcinków w tabeli Odcinki.
SELECT ll.początek.x, ll.koniec.x FROM Lines2 ll;
W Postgresie jako typów kolumn można używać typów tablicowych. Wartością atrybutu może być wtedy cała tablica, tak jak dla kolumny b poniżej.
|
Aby było to możliwe, należy najpierw zdefiniować relację jako typ, używając frazy AS TABLE OF, np.
CREATE TYPE wielobok_t AS TABLE OF punkt_t;
definiuje typ wielobok_t jako relację, której krotki są typu punkt_t, tzn. mają dwa atrybuty x i y.
Teraz można zdefiniować relację, w której jedna z kolumn będzie reprezentowała wieloboki, tzn. zbiory punktów, np.
CREATE TABLE Wieloboki ( nazwa VARCHAR2(20), punkty wielobok_t) NESTED TABLE punkty STORE AS TabPunkty;
Relacje odpowiadające poszczególnym wielobokom nie są zapisywane bezpośrednio jako wartości atrybutu punkty, lecz trzyma się je w pojedynczej tabeli, której nazwę należy zadeklarować. Do tabeli tej nie można się odwoływać bezpośrednio.
Przy wstawianiu wierszy do relacji Wieloboki używa się konstruktora typu dla zagnieżdżonej relacji (wielobok_t). Wartość zagnieżdżonej relacji podaje się w nim jako rozdzielaną przecinkami listę wartości odpowiedniego typu (punkt_t), najczęściej także używając konstruktora.
INSERT INTO Wieloboki VALUES('kwadrat', wielobok_t(punkt_t(0.0, 0.0), punkt_t(0.0, 1.0), punkt_t(1.0, 0.0), punkt_t(1.0, 1.0)));
Punkty tego kwadratu podaje poniższe zapytanie:
SELECT punkty FROM Wieloboki WHERE nazwa = 'kwadrat';