Do druku

Transkrypt

Do druku
Plan wykładu
Spis treści
1 Kolekcje
1.1 Operacje masowe .
1.2 VARRAY . . . . .
1.3 NESTED TABLES
1.4 Tabele asocjacyjne
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
2
3
6
8
2 Perspektywy obiektowe
10
3 Źródła
11
1
Kolekcje
Kolekcje
Kolekcja
jest zbiorem elementów tego samego typu. Każdy element kolekcji ma jednoznacznie określony wskaźnik określający jego położenie w kolekcji.
Kolekcje można tworzyć:
• trwale w bazie danych (VARRAY, NESTED TABLE),
• nietrwale - w blokach PL/SQL - na czas wykonania procedury lub sesji (VARRAY,
NESTED TABLE, tabele asocjacyjne).
Elementami kolekcji mogą być instancje typów obiektowych i na odwrót. Instancje kolekcji
mogą być przekazywane poprzez parametry procedur i funkcji.
Operacje na kolekcjach
• podstawianie z wykorzystaniem instrukcji podstawienia oraz przekazywania do lub
z podprogramów
• zapisywanie do tabel instrukcjami DML
• kolekcje nie mogą być używane w porównaniach oraz klauzulach DISTINCT, GROUP BY i ORDER BY
• możliwe jest przypisanie: Kolekcja1 := Kolekcja2; o ile obie instancje kolekcji są
dokładnie tego samego typu
• wymagają jawnego rozszerzania za pomocą metody EXTEND
• można je przycinać za pomocą metody TRIM
• niezainicjowana kolekcja jest równa NULL - nie ma żadnych elementów
• mogą być testowane względem NULL przy użyciu operatorów IS NULL oraz IS
NOT NULL
• do inicjalizacji służy konstruktor o tej samej nazwie co typ kolekcji lub typ obiektowy
1
• w zapytaniach można do kolekcji odwoływać się jak do tabel, stosując operator
TABLE
SELECT ... FROM TABLE(kolekcja) ...
gdzie kolekcja jest wyrażeniem lub podzapytaniem zwracającym kolekcję
• można budować perspektywy relacyjne udostępniające dane z kolekcji tak jak dane
w pełni relacyjne
• błędne operowanie kolekcjami może prowadzić do wyjątków COLLECTION IS NULL,
NO DATA FOUND, SUBSCRIPT BEYOND COUNT, SUBSCRIPT OUTSIDE LIMIT, VALUE ERROR
Metody operujące na kolekcjach
METODA
EXISTS(n)
COUNT
LIMIT
FIRST
LAST
PRIOR(n)
NEXT(n)
EXTEND
EXTEND(n)
EXTEND(n, e)
TRIM
TRIM(n)
DELETE
DELETE(n)
DELETE(n1,n2)
1.1
Opis
zwraca prawdę jeżeli n-ty element
kolekcji istnieje
zwraca liczbę elementów kolekcji
zwraca maksymalny rozmiar VARRAY
lub NULL dla tabel zagnieżdżonych
zwraca indeks pierwszego elementu kolekcji
zwraca indeks ostatniego elementu kolekcji
zwraca indeks poprzednika n-tego elementu
zwraca indeks następnika n-tego elementu
dodaje pusty element do kolekcji
dodaje n pustych elementów
dodaje n kopii elementu e
przycina kolekcję o element końcowy
przycina kolekcję o n-elementów końcowych
usuwa wszystkie elementy kolekcji
usuwa n-ty element kolekcji
usuwa elementy od n1 do n2
Operacje masowe
Operacje masowe
Operacje masowe
sposób przekazywania danych pomiędzy kolekcjami a bazą danych (ang. bulk bind ). Sprawiają, że operujemy wieloma zmiennymi jednocześnie jak jednostką. Operacje te są znacznie wydajniejsze od wykonywanych w pętli pojedynczych odczytów i zapisów.
Od wersji Oracle 8i dostępne sa dwa typy operacji masowych FORALL oraz BULK COLLECT.
Operacje masowe - FORALL
Instrukcja FORALL
• Służy do wykonywania instrukcji DML na podstawie zawartości kolekcji (oprócz
tablic asocjacyjnych indeksowanych tekstem)
• Umożliwia znaczne skrócenie zapisu:
FORALL j IN tablica.FIRST..tablica.LAST
INSERT INTO tab(kolumna) VALUES tablica(j)
2
lub:
FORALL j IN INDICES OF tablica
DELETE FROM tab WHERE kolumna=tablica(j)
gdzie INDICES OF pomija nieistniejące elementy
Operacje masowe - BULK COLLECT
Klauzula BULK COLLECT
• Służy do odczytu wyniku zapytania dotyczącego kolekcji w jednej operacji
• Może być użyta w klauzuli SELECT
SELECT ... BULK COLLECT INTO lista tablic
• Może być stosowana w klauzuli FETCH
FETCH kursor BULK COLLECT INTO ...
• Może być użyta w klauzuli RETURNING
• Nie można jej zagnieździć w pętli FORALL
Operacje masowe - przykład
CREATE OR REPLACE PROCEDURE fast_proc IS
TYPE TObjectTab IS TABLE OF ALL_OBJECTS%ROWTYPE;
ObjectTab$ TObjectTable;
BEGIN
SELECT * BULK COLLECT INTO ObjectTab$
FROM ALL_OBJECTS;
FORALL x IN ObjectTab$.First..ObjectTab$.Last
INSERT INTO t1 VALUES ObjectTab$(x);
END fast_proc;
1.2
VARRAY
VARRAY
• tablice zmiennej długości o własnościach:
– zdefiniowany maksymalny rozmiar - efektywne wykorzystanie przestrzeni bazy
danych
– zbiór uporządkowany
– wskaźniki przebiegają od 1 do aktualnego jej rozmiaru (<= maksymalnego
rozmiaru) - bez żadnych ”dziur”
– zbudowana z obiektów określonego typu (predefiniowanych, rekordowych lub
użytkownika)
– używana jeżeli będziemy pobierać jej całą zawartość podczas manipulacji obiektem
– w tabelach obiektów przechowywane razem z wierszem jak BLOB i pobierane
w całości
3
Varray w SQL
CREATE [OR REPLACE] TYPE nazwa
AS VARRAY (max_rozmiar)
OF typ_danych [NOT NULL]
• trwale przechowywane w bazie, mogą być typem atrybutu tabeli lub pola obiektu
DESC nazwa;
DESCRIBE nazwa;
DROP TYPE nazwa;
Varray w SQL - przykład
CREATE TYPE Projekt AS OBJECT (
num_proj NUMBER(3),
tytul VARCHAR2(35),
koszt NUMBER(7,2)
);
CREATE TYPE Lista AS VARRAY(3) OF Projekt;
CREATE TABLE wydzialy (
id_wydz NUMBER(2),
nazwa
VARCHAR2(15),
budzet
NUMBER(11,2),
projekty Lista
);
INSERT INTO wydzialy VALUES
(1,'Informatyka',100000,
Lista(Projekt(1,'Analiza',123),
Projekt(2,'Projekt',456)));
Varray w SQL - przykład
SELECT nazwa, projekty FROM wydzialy;
NAZWA
Informatyka
PROJEKTY
Lista(Projekt(1,Analiza,123),Projekt(2,Projekt,456))
SELECT nazwa, tytul, koszt
FROM wydzialy CROSS JOIN TABLE(wydzialy.projekty);
NAZWA
Informatyka
Informatyka
TYTUL
Analiza
Projekt
KOSZT
123
456
INSERT INTO wydzialy VALUES
(2,'Mechatronika',100000,
Lista(Projekt(1,'Skrzydlo owada', 636),
Projekt(2,'Nanorobot', 845)));
Varray w SQL + TABLE - przykład
SELECT nazwa
FROM wydzialy
WHERE 'Analiza' IN
(SELECT tytul FROM TABLE(wydzialy.projekty));
NAZWA
Informatyka
4
Varray w SQL + THE + TABLE - przykład
SELECT VALUE(x)
FROM THE(
SELECT w.projekty FROM wydzialy w
WHERE w.nazwa = 'Informatyka') x
WHERE VALUE(x) is not null;
VALUE(x)
Projekt(1,Analiza,123)
Projekt(2,Projekt,456)
Varray w PL/SQL
TYPE nazwa AS VARRAY (max_rozmiar)
OF typ_danych [NOT NULL]
• typ widoczny jedynie w ramach bloku PL/SQL
Varray w PL/SQL - przykład
DECLARE
TYPE month_va iS VARRAY(13) OF VARCHAR2(20);
v_month_va month_va;
v_count_nr NUMBER;
BEGIN
v_month_va := month_va('A','B','C','D','E','F','G');
DBMS_OUTPUT.put_line('Length:'||v_month_va.COUNT);
v_month_va.EXTEND;
v_month_va(v_month_va.LAST):='Null';
DBMS_OUTPUT.put_line('Length:'||v_month_va.COUNT);
FOR i IN v_month_va.FIRST..v_month_va.LAST
LOOP
DBMS_OUTPUT.put_line('v_month_va('||i||'): '||v_month_va(i));
END LOOP;
END;
/
Length:7
Length:8
v_month_va(1):
v_month_va(2):
v_month_va(3):
v_month_va(4):
v_month_va(5):
v_month_va(6):
v_month_va(7):
v_month_va(8):
A
B
C
D
E
F
G
Null
Varray w PL/SQL - przykład 2
DECLARE
TYPE t_kolekcja IS VARRAY(5) OF NUMBER(10);
v_kol t_kolekcja;
v_idx
NUMBER;
BEGIN
-- Inicjalizacja kolekcji.
v_kol := t_kolekcja(1, 2);
-- Rozszerzenie.
FOR i IN 3 .. 5 LOOP
v_kol.EXTEND;
v_kol(v_kol.LAST) := i;
END LOOP load_loop;
-- Nie można usuwać elementów z środka.
-- v_kol.DELETE(3);
-- Wyświetlenie zawartości
v_idx := v_kol.FIRST;
WHILE v_idx IS NOT NULL LOOP
DBMS_OUTPUT.put_line( 'The number '||v_kol(v_idx));
v_idx := v_kol.NEXT(v_idx);
END LOOP display_loop;
END;
/
The number 1
The number 2
The number 3
The number 4
The number 5
5
Varray w PL/SQL + COUNT - przykład
CREATE OR REPLACE PROCEDURE liczProjekty AS
CURSOR fcur IS
SELECT nazwa, projekty FROM wydzialy;
BEGIN
FOR j IN fcur LOOP
IF j.projekty.EXISTS(1) THEN
DBMS_OUTPUT.put_line(j.nazwa||' zawiera '|| j.projekty.count||' projekty');
END IF;
END LOOP;
END liczProjekty;
/
EXEC liczProjekty;
Informatyka zawiera 2 projekty
Mechatronika zawiera 2 projekty
Varray w PL/SQL + EXTEND + TRIM - przykład
DECLARE
TYPE month_va iS VARRAY(13) OF VARCHAR2(20);
v_month_va month_va := month_va();
v_count_nr NUMBER;
BEGIN
v_month_va.EXTEND(3);
v_month_va(1) := 'Styczeń';
v_month_va(2) := 'Luty';
v_month_va(3) := 'Marzec';
v_month_va(2) := NULL;
IF v_month_va.EXISTS(2) THEN
DBMS_OUTPUT.put_line('Obiekt istnieje');
END IF;
v_month_va.TRIM(1);
DBMS_OUTPUT.put_line('Liczba:'||v_month_va.COUNT);
DBMS_OUTPUT.put_line('Ostatni:'||v_month_va.LAST);
END;
/
Obiekt istnieje
Liczba:2
Ostatni:2
1.3
NESTED TABLES
Nested tables
TYPE nazwa AS TABLE OF typ_danych [NOT NULL]
• tabele zagnieżdżone o własnościach:
– brak maksymalnego rozmiaru - rozmiar dynamiczny
– zbiór nieuporządkowany
– używane jeżeli chcemy wyciągać pojedyncze elementy z tablicy
– w tabelach obiektów przechowywane w osobnej tabeli relacyjnej, gdzie konieczne jest podanie jej nazwy NESTED TABLE kolumna STORE AS tabela
– nie muszą być ciągłe
– nie mogą przyjmować typów: REF CURSOR, BINARY_INTEGER, PLS_INTEGER,
BOOLEAN, LONG, LONG RAW, NATURAL, NATURALN, POSITIVE, POSITIVEN, SIGNTYPE,
STRING
Nested tables w SQL
CREATE [OR REPLACE] TYPE nazwa
AS TABLE OF typ_danych [NOT NULL]
DESC nazwa;
DROP TYPE nazwa;
6
Nested tables w SQL - przykład
CREATE OR REPLACE TYPE t_wyrazy
AS TABLE OF VARCHAR2(10);
/
CREATE TABLE prac_naukowi (
id_prac number(3) PRIMARY KEY,
nazwisko VARCHAR2(20),
tytuly t_wyrazy
) NESTED TABLE tytuly STORE AS nested_tytuly;
INSERT INTO prac_naukowi VALUES
(10, 'Kowalski', t_wyrazy('mgr','dr','prof.'));
SELECT tytuly FROM prac_naukowi;
TYTULY
t wyrazy(’mgr’,’dr’,’prof.’)
SELECT COLUMN_VALUE
FROM THE (
SELECT tytuly FROM prac_naukowi
WHERE id_prac=10);
COLUMN VALUE
mgr
dr
prof.
UPDATE prac_naukowi SET
tytuly=t_wyrazy('mgr','inż.', 'dr', 'prof.')
WHERE id_prac = 10;
UPDATE THE (SELECT tytuly FROM prac_naukowi
WHERE id_prac=10)
SET COLUMN_VALUE = 'prof. zw.'
WHERE column_value = 'prof.';
Nested tables w PL/SQL
TYPE nazwa AS TABLE OF typ_danych [NOT NULL]
Nested tables w PL/SQL - przykład
DECLARE
TYPE t_listaKursow IS TABLE OF VARCHAR2(16);
v_kursy t_listaKursow;
BEGIN
v_kursy :=
t_listaKursow('AM 2010',
'PP 3401',
'BD 3100');
END;
7
Nested tables w PL/SQL + DELETE
DECLARE
TYPE month_nt IS TABLE OF VARCHAR2(20);
v_month_nt month_nt := month_nt();
i NUMBER;
BEGIN
v_month_nt.EXTEND(3);
v_month_nt(1):='A';
v_month_nt(2):='B';
v_month_nt(3):='C';
V_MONTH_NT.DELETE(2);
DBMS_OUTPUT.PUT_LINE('Liczba:'||V_MONTH_NT.COUNT);
DBMS_OUTPUT.put_line('Ostatni:'||v_month_nt.LAST);
i:=v_month_nt.FIRST;
LOOP
dbms_output.put_line(v_month_nt(i));
i:=v_month_nt.NEXT(i);
IF i IS NULL THEN EXIT;
END IF;
END LOOP;
END;
/
Liczba:2
Ostatni:3
A
C
Nested tables w PL/SQL - porównywanie
CREATE OR REPLACE PROCEDURE equal_example AS
TYPE nestedTableType IS TABLE OF VARCHAR2(10);
myTable1 nestedTableType;
myTable2 nestedTableType;
mytable3 nestedtabletype;
result BOOLEAN;
BEGIN
myTable1 := nestedTableType('A', 'B', 'C');
myTable2 := nestedTableType('A', 'B', 'D');
myTable3 := nestedTableType('A', 'B', 'E');
result := mytable1 = mytable2;
IF result then
DBMS_OUTPUT.PUT_LINE('myTable1 jest równa myTable2' );
ELSE
DBMS_OUTPUT.PUT_LINE('myTable1 NIE jest równa myTable2' );
END IF;
result := myTable1 <> myTable3;
IF result then
DBMS_OUTPUT.PUT_LINE('myTable1 nie jest równa myTable3');
END IF;
END equal_example;
/
CALL equal_example();
myTable1 NIE jest równa myTable2
myTable1 nie jest równa myTable3
1.4
Tabele asocjacyjne
Tabele asocjacyjne
• tabele asocjacyjne posiadają własności:
– struktury jednowymiarowe
– nie wymagają inicjowania oraz konstruktora
– indeksacja liczbami, a od wersji 10g także łańcuchami znaków o zmiennej długości
– jako wartości indeksów można używać dowolnych liczb całkowitych (ujemnych,
zera i dodatnich)
– indeksy nie muszą być uporządkowane
– rozmiar tablicy jest dynamiczny
– tabela jest tworzona w momencie przypisania wartości pierwszemu elementowi
– tablica składa się z dwóch kolumn: klucza oraz wartości (skalarnej lub złożonej)
8
Definicja
TYPE nazwa_typu IS TABLE OF {
typ_elementu| zmienna%TYPE| tabela.kolumna%TYPE
} [NOT NULL]
| tabela%ROWTYPE
INDEX BY [PLS_INTEGER | BINARY_INTEGER |
VARCHAR2(rozmiar)];
identyfikator nazwa_typu;
Przykład I
DECLARE
TYPE t_kolekcja IS TABLE OF NUMBER(10)
INDEX BY BINARY_INTEGER;
v_kol t_kolekcja;
v_idx
NUMBER;
BEGIN
-- Inicjalizacja
FOR i IN 1 .. 5 LOOP
v_kol(i) := i;
END LOOP load_loop;
-- Wykasowanie trzeciego elementu
v_kol.DELETE(3);
-- Wyświetlenie
v_idx := v_kol.FIRST;
WHILE v_idx IS NOT NULL LOOP
DBMS_OUTPUT.PUT_LINE('The number ' || v_kol(v_idx));
v_idx := v_kol.NEXT(v_idx);
END LOOP display_loop;
END;
/
The
The
The
The
number
number
number
number
1
2
4
5
Przykład II
DECLARE
TYPE typ_tablica_str_int IS TABLE OF NUMBER INDEX BY VARCHAR2(100);
wiek_osob_tablica typ_tablica_str_int;
TYPE typ_tablica_str_str IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
ranking_tablica typ_tablica_str_str;
BEGIN
wiek_osob_tablica('Jan Kowalski') := 45;
wiek_osob_tablica('Tomasz Nowak') := 33;
dbms_output.put_line('Wiek Jan Kowalski:' ||wiek_osob_tablica('Jan Kowalski'));
ranking_tablica(1) := 'Pawel Romaniuk';
ranking_tablica('22') := 'Artur Kwiatkowsk';
dbms_output.put_line('Pozycja 1: ' || ranking_tablica(1));
dbms_output.put_line('Pozycja 2: ' || ranking_tablica(22));
dbms_output.put_line('Pozycja nieznana:'|| ranking_tablica('tego nie ma'));
EXCEPTION WHEN no_data_found THEN
dbms_output.put_line('EXCEPTION: Brak danych');
END;
/
Wiek Jan Kowalski:45
Pozycja 1: Pawel Romaniuk
Pozycja 2: Artur Kwiatkowsk
EXCEPTION: Brak danych
Tabele asocjacyjne + DELETE
DECLARE
TYPE t_ValueTable IS TABLE OF VARCHAR2(10)
INDEX BY BINARY_INTEGER;
v_Values t_ValueTable;
BEGIN
v_Values(1) := 'Jeden';
v_Values(3) := 'Trzy';
v_Values(-2) := 'Minus dwa';
v_Values(0) := 'Zero';
v_Values(100) := 'Sto';
DBMS_OUTPUT.PUT_LINE('Liczba elementów '||v_values.COUNT);
v_Values.DELETE(100); -- Usuwa 100
DBMS_OUTPUT.PUT_LINE('Liczba elementów '||v_values.COUNT);
v_Values.DELETE(-2, 1); -- Usuwa zakres od -2 do 1
DBMS_OUTPUT.PUT_LINE('Liczba elementów '||v_values.COUNT);
v_Values.DELETE;
-- Usuwa pozostałe wartości
DBMS_OUTPUT.PUT_LINE('Liczba elementów '||v_values.COUNT);
END;
9
/
Liczba
Liczba
Liczba
Liczba
elementów
elementów
elementów
elementów
5
4
1
0
Tabele asocjacyjne + EXISTS
DECLARE
Type t_FirstNameTable IS TABLE OF VARCHAR(20)
INDEX BY BINARY_INTEGER;
FirstNames t_FirstNameTable;
BEGIN
FirstNames(1) := 'Scott';
FirstNames(3) := 'Joanne';
IF FirstNames.EXISTS(1) THEN
DBMS_OUTPUT.put_line('Row 1 exists!');
ELSE
DBMS_OUTPUT.put_line('Row 1 doesn''t exist!');
END IF;
IF FirstNames.EXISTS(2) THEN
DBMS_OUTPUT.put_line('Row 2 exists!');
ELSE
DBMS_OUTPUT.put_line('Row 2 doesn''t exist!');
END IF;
END;
/
Row 1 exists!
Row 2 doesn't exist!
Zestawienie kolekcji
Cecha
Tablice
asocjacyjne
Nested
table
Varray
Wymiar
W SQL
W PL/SQL
Inicjalizacja
jednowymiarowe
nie
tak
automatyczna,
podczas deklaracji
tak
jednowymiarowe
tak
tak
przez kontruktor, fetch
lub przypisanie
po inicjalizacji nie,
po kasowaniu tak
może być rozszerzany
może wymagać
rozszerzenia
jednowymiarowe
tak
tak
przez kontruktor, fetch
lub przypisanie
nie
Rozrzucony
Ograniczony
Umożliwia przypisanie
do dowolnego elementu
nie
tak
Sposób rozszerzania
przypisanie wartości
do nowego klucza
poprzez procedurę
EXTEND
tak
może wymagać
rozszezrzenia, ale nie
ponad limit
poprzez procedurę
EXTEND
Dopasowanie kolekcji
• Tablice zagnieżdżone są bardziej elastyczne jako kolumny tabel od VARRAY
• VARRAY są najlepszym rozwiązaniem kiedy wymagamy uporządkowania i ograniczenia rozmiaru
• tablice asocjacyjne zapewniają dowolność indeksacji już na poziomie inicjalizacji
2
Perspektywy obiektowe
Perspektywy obiektowe
Perspektywa obiektowa
jest wirtualna tabelą obiektową. Stanowi rozszerzenie mechanizmu perspektyw relacyjnych.
Cechy perspektyw obiektowych:
• prezentują dane relacyjne w sposób relacyjno-obiektowy
• umożliwiają wykorzystanie technik programowania obiektowego pozostawiając niezmienionym model logiczny danych
• umożliwiają stosowanie obiektów w językach programowania i zapytaniach (np. dereferencje zamiast złączeń)
• zmniejszają ruch w sieci (obiekty są “montowane” na serwerze i przesyłane w całości)
• umożliwiają aktualizację danych bazowych jeżeli nie ma niejasności interpretacji
10
Perspektywy obiektowe - definicja
CREATE VIEW nazwa OF typ obiektowy
[WITH OBJECT IDENTIFIER (kolumny)]
AS SELECT...
Klauzula WITH OBJECT IDENTIFIER (Id) określa jednoznaczny identyfikator dla tworzonych obiektów perspektywy.
Przykład
-- typ obiektowy
CREATE OR REPLACE TYPE Typ_osoby AS OBJECT (
Id
INTEGER,
Nazwisko VARCHAR2(50)
);
-- tabela relacyjna
CREATE TABLE Osoby (
Id
INTEGER,
Nazwisko VARCHAR2(50)
);
-- perspektywa obiektowa
CREATE VIEW Ob_osoby OF Typ_osoby
WITH OBJECT IDENTIFIER (Id)
AS SELECT Id, Nazwisko FROM Osoby;
3
Źródła
Źródła
W wykładzie wykorzystano materiały:
• http://stencel.mimuw.edu.pl/obd/objrel.html
• http://www.java2s.com/Tutorial/Oracle/0520__Collections/Catalog0520__Collections.
htm
• http://www.dba-oracle.com/plsql/t_plsql_varrays.htm
• http://www.ia.pw.edu.pl/~ttraczyk/kbd/kbd_4.pdf
• http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/05_colls.
htm
• http://ii.uwb.edu.pl/~aboltuc/images/stories/bazy_danych_2/wykad_5.pdf
• http://docstore.mik.ua/orelly/oracle/prog2/ch19_01.htm
• C.Zaniolo, S.Ceri, Ch.Faloutsos, R.T. Snodgrass, V. S. Subrahmanian, R.Zicari,
Advanced Database Systems, Morgan Kaufmann, 1997
• M. Lentner, Oracle 9i Kompletny podręcznik użytkownika, PJWSTK - W-wa, 2003
11

Podobne dokumenty