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