Wykład 7

Obiektowość w obiektowo-relacyjnych bazach danych na przykładzie Oracle

 

Streszczenie

Współczesne bazy danych posiadają cechy zarówno relacyjne jak i obiektowe. Do tej pory poznaliśmy cechy relacyjne, teraz czas na poznanie cech obiektowych.

Rozważymy dwa rodzaje obiektów, które można przechowywać w obiektowo-relacyjnej bazie danych:

 


7.1 Znaczenie obiektowości w bazach danych

Od dwudziestu już lat trwają prace nad nowymi koncepcjami w bazach danych polegającymi na dołączaniu cech obiektowych do istniejących relacyjnych baz danych. Otrzymano w ten sposób model obiektowo-relacyjny i faktycznie na takim modelu jest w tej chwili oparty nowy Standard języka SQL:1999.

Przypomnimy najpierw ogólne znaczenie typów obiektowych. Realizują one zasadę abstrakcji w dwóch postaciach:

Oto podsumowanie zalet użycia obu rodzajów abstrakcji w bazach danych:

  1. Ułatwione modelowanie rzeczywistych obiektów biznesowych.
  2. Zmniejszenie złożoności tworzenia aplikacji przez podział zadania na części. Ułatwienie dokonywania zmian. Ukrycie szczegółów implementacyjnych przed użytkownikiem. Modularność aplikacji i możliwość wielokrotnego użycia komponentów w tej samej lub w różnych aplikacjach.
  3. Zgrupowanie używanego kodu po stronie serwera wokół obiektów, na których kod działa. Uzyskanie większej kontroli nad kodem.
  4. Zastosowanie obiektowo-relacyjnego modelu danych prowadzi do zmniejszenia rozbieżności w modelach danych samej bazy danych i aplikacji bazodanowej napisanej w obiektowym języku programowania. Oba modele można oprzeć o te same pojęcia: klasy (typu obiektowego) i instancji klasy (obiektu).

7.2 Typ obiektowy

Typ obiektowy, odpowiadający pojęciu klasy w obiektowych językach programowania, jest to złożony typ danych, który hermetyzuje strukturę danych łącznie z metodami potrzebnymi do operowania na strukturze danych. Definiując typ obiektowy określamy atrybuty i metody obiektów np. typ obiektowy zamówienia.

Rys. 7.1 Struktura obiektu
 

Struktura typu obiektowego

Osobno specyfikujemy publiczny interfejs obiektów składający się z deklaracji atrybutów i specyfikacji metod oraz prywatną implementację  obiektów składającą się z definicji (ciał) metod.

Rys. 7.2 Struktura typu obiektowego
 

Oto składnia specyfikacji typu obiektowego (w wersji podstawowej):
 
CREATE TYPE nazwa_typu AS OBJECT
(atrybut typ_danych, ...
MEMBER sygnatura procedury lub funkcji
[, klauzula PRAGMA], ...
);

Oto składnia implementacji typu obiektowego (w wersji podstawowej):
 
CREATE TYPE BODY nazwa_typu AS
MEMBER implementacja procedury lub funkcji; ... END;

Przykład

Zdefiniujemy dwa typy obiektowe: typ nazwisk Name_typ oraz typ pracowników Emp_typ:

CREATE TYPE Name_typ
AS OBJECT(
   F_name VARCHAR2(25),
   L_name VARCHAR2(25),
   Initials VARCHAR2(7),
   MEMBER FUNCTION Full_name RETURN VARCHAR2,
   PRAGMA RESTRICT_REFERENCES(Full_name, WNDS, RNDS, WNPS, RNPS ));
/
CREATE TYPE BODY Name_typ AS
   MEMBER FUNCTION Full_name RETURN VARCHAR2 IS
   BEGIN
      RETURN (L_name || ' ' || F_name );
   END Full_name;
END;
/
CREATE TYPE Emp_typ
AS OBJECT(
   Emp_id NUMBER(7),
   Name Name_typ,           -- typ obiektowy
   Street VARCHAR2(25),
   City VARCHAR2(15),
   State CHAR(2),
   Zip INTEGER,
   MEMBER FUNCTION Get_name RETURN VARCHAR2,
   PRAGMA RESTRICT_REFERENCES(Get_name, WNDS, RNDS, WNPS, RNPS),
   MEMBER PROCEDURE Set_l_name (v_name VARCHAR2));
/
CREATE TYPE BODY Emp_typ AS
   MEMBER FUNCTION Get_name RETURN VARCHAR2 IS
   BEGIN
      RETURN (Name.L_name ||' '|| Name.F_name);
   END;
   MEMBER PROCEDURE Set_l_name (v_name VARCHAR2) IS
   BEGIN
     Name.L_name := v_name;
   END;
END;
/

Metody

Metody to funkcje lub procedury, które tworzymy w definicji typu obiektowego w celu zaimplementowania zachowania się obiektów danego typu. Aplikacja wywołuje metody aby uzyskać w efekcie to zachowanie. Są trzy typy metod: metody składowe obiektów (metody typu MEMBER), metody konstruktorów obiektów (metody typu CONSTRUCTOR) oraz metody statyczne, czyli odnoszące się do całego typu (metody typu STATIC). W tym wykładzie rozważamy tylko metody składowe obiektów oraz metody konstruktora obiektów implementowane przez system – oprócz tego są jeszcze metody konstruktorów definiowane przez użytkowników.

Dziedziczenie

Między typami obiektowymi obowiązuje dziedziczenie tak jak w językach programowania - realizowane przez operator UNDER. Na przykład:

CREATE TYPE Person
AS OBJECT (
  First VARCHAR2(50),
  Last VARCHAR2(50)) NOT FINAL;
/

CREATE TYPE Emp
UNDER Person (
  Salary NUMBER) FINAL;
/

Obiekt typu Emp ma wszystkie cechy obiektu typu Person a poza tym jeszcze cechy wprowadzone w specyfikacji typu Emp.

DECLARE
  x Emp:=Emp('Jan','Kowalski',10000);
BEGIN
  DBMS_OUTPUT.Put_line(x.first||' '||x.last||' '||x.salary);
END;
/

Wymagana jest specyfikacja NOT FINAL dla typów obiektowych, które mogą być wzorcami dla podtypów podlegając dalszemu dziedziczeniu czyli nie są one końcowe w hierarchii dziedziczenia. Domyślną specyfikacją jest FINAL - typ obiektowy nie podlega dalszemu dziedziczeniu.

Przesłanianie

Tak jak w językach programowania jest możliwość zastosowania przesłaniania metod.

CREATE TYPE Figure
AS OBJECT (
  NOT INSTANTIABLE MEMBER FUNCTION area RETURN NUMBER
) NOT INSTANTIABLE NOT FINAL;
/

CREATE TYPE Rect
UNDER Figure
  (x NUMBER,
   y NUMBER,
   OVERRIDING MEMBER FUNCTION area RETURN NUMBER) FINAL;
/

CREATE TYPE BODY Rect AS
  OVERRIDING MEMBER FUNCTION area RETURN NUMBER IS
  BEGIN
     RETURN x*y;
  END;
END;
/

Definicja metody area w podtypie Rect przesłania jej specyfikację w nadtypie Figure. Wymagane jest słowo kluczowe OVERRIDING. Domyślną specyfikacją metody jest NON OVERRIDING.

Słowo kluczowe NON INSTANTIABLE dla typu obiektowego oznacza, że nie można tworzyć instancji danego typu obiektowego a dla metody -  brak implementacji. Domyślną specyfikacją w obu przypadkach jest INSTANTIABLE.

Informacje w słowniku danych Oracle

Informacje o typach obiektowych znajdują się w perspektywie słownika danych o nazwie:

Informacje o metodach typów obiektowych znajdują się odpowiednio w perspektywach słownika danych:

Usuwanie typów obiektowych

Oprócz instrukcji usuwania typu obiektowego, która usuwa zarówno implementację jak i specyfikację typu obiektowego, jest też instrukcja usuwania samej implementacji typu obiektowego z pozostawieniem jego specyfikacji. W tym momencie do istniejących obiektów tego typu nie można zastosować żadnej z metod!
 
DROP TYPE typ;

DROP TYPE BODY typ_obiektowy;

 

7.3 Tabela obiektowa

Zdefiniowanego typu obiektowego można używać do tworzenia tabel obiektowych tego typu.
 
CREATE TABLE nazwa_tabeli OF nazwa_typu
[(więzy spójności)];

Zauważmy, że więzów spójności nie określa się w definicji typu obiektowego, tylko w definicji samej tabeli.

W utworzonej tabeli obiektowej są zapisywane obiekty typu obiektowego na tej samej zasadzie co wiersze tabeli relacyjnej. To znaczy, wartości atrybutów tworzą wiersz, na którym działają metody określone w danym typie obiektowym.

CREATE TABLE Name_table OF Name_typ;  -- tabela obiektowa

INSERT INTO Name_table
VALUES('Jan','Kowalski','JK');

INSERT INTO Name_table
VALUES('Anna','Kowalska','AK');

SELECT nt.F_name, nt.Full_name()
FROM Name_table nt;

Metoda konstruktora obiektu

Dla każdego typu obiektowego automatycznie jest tworzona metoda konstruktora obiektu tego typu. Ma ona taką samą nazwę jak typ obiektowy oraz ma argumenty takich typów jak atrybuty typu obiektowego. Rozważmy typ obiektowy:

CREATE TYPE Tv_type
AS OBJECT (
  Tv_category VARCHAR2(20),
  Screen_size NUMBER(4));
/

Oto przykłady użycia jego konstruktora w bloku PL/SQL:

DECLARE
  v_new_tv tv_type := Tv_type('WEB tv', 32);
  v_alt_tv Tv_type;
BEGIN
  v_alt_tv := Tv_type('Big Screen', 72);
END;
/

oraz w instrukcji INSERT do tabeli obiektowej:

CREATE TABLE Tv OF Tv_type;

INSERT INTO Tv VALUES(Tv_type('Color tv', '28'));

Wyszukiwanie (SELECT) w tabeli obiektowej

Wynikiem instrukcji:

SELECT *
FROM Name_table p
WHERE p.L_name LIKE 'K%';
jest zbiór wierszy:
F_NAME         L_NAME        INITIAL
-------------- ------------- -------
Jan            Kowalski      JK
Anna           Kowalska      AK

Wynikiem instrukcji:

SELECT VALUE(p) AS Osoba
FROM Name_table p
WHERE p.L_name LIKE 'K%';

jest zbiór obiektów reprezentowanych przy użyciu konstruktora typu obiektowego (VALUE(p) - oznacza obiekt wskazywany przez p):

OSOBA(F_NAME, L_NAME, INITIALS)
-----------------------------------
NAME_TYP('Jan', 'Kowalski', 'JK')
NAME_TYP('Anna', 'Kowalska', 'AK')
 

Wstawianie (INSERT) do tabeli obiektowej

Wstawiamy albo bezpośrednio tak jak do tabeli relacyjnej:

INSERT INTO Name_table
VALUES('Jan','Kowalski','JK');
albo z użyciem konstruktora:
INSERT INTO Name_table
VALUES(Name_typ('Jan','Kowalski','JK'));

Modyfikacja (UPDATE) na tabeli obiektowej

Modyfikujemy albo bezpośrednio, tak jak w tabeli relacyjnej:

UPDATE Name_table p
SET p.L_name = 'Janusz'
WHERE p.L_name = 'Jan';
albo z użyciem konstruktora:
UPDATE Name_table p
SET p = Name_typ('Janusz','Kowalski','JK')
WHERE p.L_name = 'Jan';

Usuwanie obiektów (DELETE) z tabeli obiektowej

Obiekty z tabeli obiektowej usuwamy tak jak wiersze z tabeli relacyjnej:

DELETE FROM Name_table p
WHERE p.L_name = 'Janusz';

Tabela relacyjna w obiektowo-relacyjnej bazie danych

Oprócz nowego rodzaju tabel obiektowych możemy także używać tabel relacyjnych z kolumnami typów obiektowych. Wartościami wpisywanymi do kolumn tabeli mogą więc być instancje typów obiektowych. Na przykład:

CREATE TABLE Emp1(  -- tabela relacyjna
   Empno NUMBER PRIMARY KEY,
   Name Name_typ,   -- kolumna typu obiektowego
   Sal NUMBER,
   Kier REFERENCES Emp1);

Typ referencyjny

Dla każdego typu obiektowego Type jest automatycznie definiowany jego typ referencyjny oznaczany przez REF Type. Typu tego można używać jako typu atrybutów obiektów bądź kolumn w tabeli relacyjnej. Daje to możliwość wiązania wartości atrybutu bądź wartości w kolumnie z innym obiektem podobnie jak klucz obcy odwołuje się do klucza głównego. Jest to alternatywny sposób tworzenia powiązań.

CREATE TYPE Dept_Type
AS OBJECT(
   Name VARCHAR2(10),
   Loc VARCHAR2(50));
CREATE TYPE Emp_Type
AS OBJECT(
   Name VARCHAR2(20),
   Sal NUMBER,
   Dept_ref REF Dept_Type);
CREATE TABLE Obj_Dept OF Dept_Type;

CREATE TABLE Obj_Emp OF Emp_Type -- tabela obiektowa
(Dept_ref SCOPE IS Obj_Dept);

CREATE TABLE Rel_emp(            -- tabela relacyjna
  Id NUMBER PRIMARY KEY,
  Name VARCHAR2(20),
  Sal Number,
  Dept_ref REF Dept_Type SCOPE IS Obj_Dept);

Ze względu na możliwość istnienia wielu tabel obiektowych tego samego typu, definiując typ referencyjny trzeba wskazać do obiektów której tabeli odwołuje się on. Służy do tego klauzula SCOPE IS – proszę zwrócić uwagę na jej użycie w powyższych przykładach.

W instrukcjach SQL można bezpośrednio nawigować przez referencje w taki sam sposób jak to ma miejsce dla obiektów. Gdybyśmy chcieli dla każdego pracownika wypisać nazwę jego departamentu, użylibyśmy następującej instrukcji SELECT:

SELECT e.Name, e.Dept_ref.Name
FROM Obj_emp e;

Dla tabeli relacyjnej instrukcja SELECT jest taka sama.

SELECT e.Name, e.Dept_ref.Name
FROM Rel_emp e;

Natomiast w kodzie PL/SQL nawigacja przez referencje jest niedozwolona i wymaga użycia specjalnej funkcji SQL:
 
   DEREF(p) - obiekt na który wskazuje referencja p

Jest też funkcja odwrotna:
 
   REF(o) - referencja do obiektu o identyfikatorze o

Reasumując, w obiektowo-relacyjnej bazie danych pojawiają się dwa nowe rodzaje wartości związane z zapisem danych na dysku: referencje do obiektów oraz jednoznaczne identyfikatory obiektów. Każda implementacja obiektowo-relacyjnej bazy danych może używać innych zbiorów tych wartości, co powoduje, że obiektowo-relacyjna baza danych przestaje być przenaszalna (jako zbiór tabel z atomowymi, skalarnymi wartościami) między różnymi systemami. Tracimy więc wielką zaletę relacyjnych baz danych.

Kolekcje

Atrybut typu obiektowego lub kolumna tabeli nie koniecznie musi być typu prostego ale może być typu zbiorowego (kolekcji). Są dwa rodzaje kolekcji:

  1. VARRAY – typ tablicy jednowymiarowej (jak wektor);
  2. TABLE – typ tabeli zagnieżdżonej. A więc wartością atrybutu może być cała tabela! Tego typu nie będziemy rozważać na wykładzie.

Oto przykład zastosowania typu VARRAY. Najpierw definicja typu obiektowego o nazwie Projekt.

CREATE TYPE Projekt AS OBJECT (
   Num_proj NUMBER(3),
   Tytuł VARCHAR2(35),
   Koszt NUMBER(7,2));
Teraz zdefiniujemy typ kolekcji o nazwie Lista – mianowicie tablicę VARRAY projektów. Jako argument VARRAY podajemy górne ograniczenie liczby projektów - w naszym przykładzie będzie to liczba 3.
CREATE TYPE Lista AS
 VARRAY(3) OF Projekt;
Oto definicja tabeli, w której jeden z atrybutów o nazwie Projekty jest typu tablicowego Lista.
CREATE TABLE Wydziały (
   Id_wydz NUMBER(2),
   Nazwa VARCHAR2(15),
   Budżet NUMBER(11,2),
   Projekty Lista);
Do inicjacji wartości kolekcji służy funkcja konstruktora o tej samej nazwie co typ kolekcji. A więc do tabeli Wydziały wstawiamy wartości atrybutów kolekcji w następujący sposób – należy tylko pamiętać aby zgodnie ze specyfikacją tablica Projekty nie miała więcej niż trzy elementy (ale może mieć mniej).
INSERT INTO Wydziały 
VALUES(1,'Informatyka',100000, Lista(Projekt(1,'Analiza',123), Projekt(2,'Projekt',456)));
Również w takiej postaci system wypisuje wartości kolekcji przy wykonywaniu instrukcji SELECT. Wynik instrukcji
SELECT w.Nazwa, w.Projekty
 FROM Wydziały w;
jest wypisywany w postaci:
NAZWA       PROJEKTY(NUM_PROJ, TYTUŁ, KOSZT)
----------- --------------------------------------------------------
Informatyka LISTA(PROJEKT(1,'Analiza',123),PROJEKT(2,'Projekt',456))
Natomiast tylko w kodzie PL/SQL do poszczególnych elementów kolekcji można dostawać się używając naturalnej dla tablic składni:
 
Nazwa_kolekcji(wskaźnik)

Przykład

Przy reprezentowaniu departamentów i pracowników za pomocą dwóch tabel obiektowych Obj_Dept i Obj_Emp odpowiednio typów Dept_Type i Emp_Type, łatwo jest wyznaczyć dla pracownika jego departament (poprzez atrybut Dept_ref). Natomiast wobec braku klucza obcego i indeksu na nim, trudno wyznaczyć dla danego departamentu wszystkich pracowników zatrudnionych w tym departamencie. Rozwiązaniem tego problemu jest zastosowanie kolekcji. Definiujemy typ kolekcji

CREATE TYPE Pracownicy AS VARRAY(100) OF REF Emp_Type;
i do typu Dept_Type dodajemy atrybut Kadra typu tej kolekcji. Oto pełne rozwiązanie.
CREATE TYPE Dept_Type
AS OBJECT(
   Name VARCHAR2(10),
   Loc VARCHAR2(50),
   Kadra Pracownicy);        --  pracownicy w departamencie
/
CREATE TYPE Emp_Type
AS OBJECT(
   Name VARCHAR2(20),
   Sal NUMBER,
   Dept_ref REF Dept_Type);  --  departament pracownika
/
CREATE TABLE Obj_Dept OF Dept_Type;

CREATE TABLE Obj_Emp OF Emp_Type
(Dept_ref SCOPE IS Obj_Dept);

Przykład

Zaprezentujemy przetwarzanie wartości w kolekcji przy użyciu kodu PL/SQL. Wypiszemy wydziały razem z projektami realizowanymi w tych wydziałach. Użyjemy metody Count zdefiniowanej dla kolekcji. Wartością Nazwa_kolekcji.Count jest liczba elementów w kolekcji. Metoda ta pozwala przejrzeć wszystkie elementy kolekcji.

CREATE OR REPLACE PROCEDURE Wypisz AS
   lis Lista;
BEGIN
   FOR z IN (SELECT * FROM Wydzialy) LOOP
      DBMS_OUTPUT.Put_line('Projekty Wydzialu: '||z.Nazwa);
      lis:=z.Projekty;
      FOR i IN 1..lis.Count LOOP
        DBMS_OUTPUT.Put_line(lis(i).Num_proj||' '||lis(i).Tytul);
      END LOOP;
   END LOOP;
END;

Realizacja polecenia:

    Exec Wypisz

spowoduje wyświetlenie (należy pamiętać o włączeniu opcji SET SERVEROUTPUT ON):

Projekty Wydzialu: Informatyka
1 Analiza
2 Projekt
 



7.4 Duże obiekty LOB

Język SQL i jego rozszerzenie PL/SQL w dotychczas omawianej postaci umożliwiają dostęp do standardowych typów danych zapisanych w bazie danych i umożliwiają wykonywanie na nich operacji. Są jednak sytuacje, gdy może się to okazać niewystarczające.

Z taką sytuacją mamy do czynienia w przypadku danych, których format wykracza poza format standardowych typów danych. Przykładem takich danych są duże obiekty, jak rysunki (grafika), fotografie, zdjęcia satelitarne i rentgenowskie (zdjęcia binarne), video, animacje, wywiady (audio/video), muzyka, odgłosy dźwiękowe (sound waveforms), skrypty, dokumenty tekstowe, książki. Wprowadzono więc, zarówno do Standardu SQL:1999, jak i do Oracle nowe typy danych dla dużych obiektów tzw. LOB (ang. large objects). Oprócz samych dużych obiektów wspomnimy również krótko o narzędziach do operowania na nich dostarczonych w standardowym pakiecie Oracle o nazwie DBMS_LOB.

Operowanie dużymi obiektami w Oracle (pakiet DBMS_LOB)

W Oracle są cztery rodzaje dużych obiektów LOB:
 
  1. BLOB – binarny duży obiekt - strumień bitów jak w przypadku LONG RAW.
  2. CLOB – znakowy duży obiekt - strumień znaków (pojedynczych bajtów).
  3. NCLOB – uogólniony (dla języków narodowych wielobajtowych) znakowy duży obiekt.
  4. BFILE – plik binarny przechowywany poza bazą danych.

Rys. 7.3 Rodzaje dużych obiektów
 

Duże obiekty są przechowywane albo wewnętrznie - wewnątrz bazy danych – dotyczy to wartości typów CLOB, NCLOB, BLOB, albo zewnętrznie w plikach systemu operacyjnego – dotyczy to wartości typu BFILE, które są dostępne z serwera Oracle tylko w trybie odczytu. Serwer Oracle nie potrafi automatycznie dokonywać konwersji danych między różnymi typami danych, np. z wartości typu CLOB do wartości typu BLOB.

Z każdym dużym obiektem LOB jest związana:

  1. wartość LOB: przechowywana w bazie danych zawartość dużego obiektu,
  2. lokalizator LOB: wskaźnik do wartości LOB przechowywanej w bazie danych.

Zasada jest taka, że w kolumnie typu LOB jest zapisywany lokalizator LOB – nie cała jego zawartość. Interfejsy programistyczne operujące wartościami LOB używają tych lokalizatorów w podobny sposób, jak używa się uchwytów do plików w systemie operacyjnym. Przypisując lokalizator do nowej zmiennej lub nowego wiersza następuje skopiowanie wartości dużego obiektu i wygenerowanie nowego lokalizatora. W przypadku zewnętrznych wartości LOB nie są one kopiowane (a więc wskaźnik do tego samego pliku BFILE może występować w różnych wierszach w tabeli).

Poniższy rysunek ilustruje fakt, że wartością atrybutu, kolumny lub zmiennej jest lokalizator (wskaźnik) do dużego obiektu LOB, który jest zapisany albo w samej bazie danych albo poza nią (w przypadku wartości BFILE).

Rys. 7.4 Reprezentacja dużego obiektu
 

Przykład

Rozważmy tabelę pracowników, której kolumny są typów LOB. Dla każdego pracownika zamieszczamy jego życiorys (Resume), zdjęcie (Picture) oraz film video (Video).

CREATE TABLE Employee(
   Empno NUMBER,
   Ename VARCHAR2(35),
   Resume CLOB,
   Picture BLOB,
   Video BFILE);

Zewnętrzne obiekty LOB typu BFILE

Zewnętrzne obiekty LOB nie są zapisywane w bazie danych lecz każdy w osobnym pliku systemu operacyjnego.

W systemie Oracle został wprowadzony nowy rodzaj obiektu bazodanowego o nazwie katalog związany z typem danych BFILE. Mianowicie, katalog jest to obiekt bazodanowy reprezentujący katalog systemu operacyjnego. Służy do administrowania dostępem do obiektów bazy danych typu BFILE przechowywanych w plikach poza bazą danych. Fizyczny katalog jest tworzony pod systemem operacyjnym z uprawnieniami odczytu dla procesów Oracle. Pliki w tym katalogu nie mogą być ani zmieniane ani usuwane przez system Oracle.

Na przykład, instrukcja:

CREATE DIRECTORY Videos AS '/oracle/lob/';

tworzy obiekt bazodanowy reprezentujący katalog /oracle/lob

Rys. 7.5 Obiekt bazy danych typu katalog
 

Zilustrujemy użycie obiektów LOB w instrukcjach SQL na kilku przykładach.

Wstawianie obiektów LOB

INSERT INTO Employee VALUES
(7897,'Jan Kowalski','Znakomity aktor', NULL, NULL);

INSERT INTO Employee VALUES
(7898,'Piotr Jankowski', Empty_CLOB(), Empty_BLOB(), Bfilename('VIDEOS','J.IMG'));

UPDATE Employee e
  SET e.Resume =(SELECT f.Resume FROM Employee1 f
                 WHERE f.Ename='Kowalski')
WHERE e.Empno = 4508;

W powyższym przykładzie NULL oznacza brak lokalizatora obiektu LOB, Empty_BLOB() i Empty_CLOB() oznaczają lokalizator do pustego obiektu. Stałe tekstowe zostają automatycznie przekształcone do typu CLOB. Natomiast, funkcja Bfilename('VIDEOS','J.IMG')) zwraca lokalizator dużego obiektu przechowywanego w pliku J.IMG.

Dopisywanie do obiektów LOB w PL/SQL

Na zawartościach obiektów BLOB i CLOB można operować za pomocą procedur i funkcji specjalnego pakietu DBMS_LOB w podobny sposób jak to się robi na zawartościach plików binarnych.

DECLARE
  lobloc CLOB; -- lokalizator LOB
  text VARCHAR2(2000);
  amount NUMBER;
  offset INTEGER;
BEGIN
  text := 'tekst do wpisania do LOB';
  SELECT e.Resume INTO lobloc
    FROM Employee e WHERE e.Empno = 5887
  FOR UPDATE; -- konieczna blokada wiersza
  offset := DBMS_LOB.Getlength(lobloc) + 1;
  amount := Length(text);
  DBMS_LOB.Write(lobloc, amount, offset, text);
  COMMIT;
  DBMS_OUTPUT.Put_line('Wpisano ' || To_char(amount) ||' znaków');
END;
/

W szczególności, procedura DBMS_LOB.Write(lobloc, amount, offset, text) dopisuje do istniejącej zawartości obiektu o lokalizatorze lobloc zawartość text o długości amount począwszy od miejsca offset. Oto jej sygnatura:

PROCEDURE Write(
	Lobdst IN OUT BLOB|CLOB, -- dwie możliwości
	Amount IN OUT BINARY_INTEGER,
	Offset IN INTEGER := 1,
	Buffer IN RAW|VARCHAR2) -- RAW dla BLOB, VARCHAR2 dla CLOB

Jak widać, nie jest przewidziana możliwość wpisywania danych do obiektu typu BFILE!

Oto sygnatura funkcji Read odczytującej określoną przez amount ilość danych dużego obiektu BLOB, CLOB lub BFILE od jego pozycji offset i zapisującą je do bufora buffer:

PROCEDURE Read(
 	Lobsrc IN BFILE|BLOB|CLOB , -- trzy możliwości!
 	Amount IN OUT BINARY_INTEGER,
	Offset IN INTEGER,
	Buffer OUT RAW|VARCHAR2)
-- RAW dla BLOB i BFILE, VARCHAR2 dla CLOB
Jest też możliwość załadowania zawartości obiektu BFILE (czyli pliku binarnego) do bazy danych w postaci obiektu BLOB lub CLOB. Służy do tego procedura Loadfromfile o następującej sygnaturze:
PROCEDURE Loadfromfile(
        Lobdst  IN OUT BLOB|CLOB,
        Src_file    IN  BFILE,
        Amount      IN  INTEGER,
        Dest_offset IN  INTEGER  := 1,
        Src_offset  IN  INTEGER  := 1)

Oto przykład użycia procedury Loadfromfile do wstawienia zdjęcia osoby dostępnego jako obiekt typu BFILE - do tabeli Emp w postaci obiektu wewnętrznego typu BLOB:

CREATE TABLE Emp(
  Empno INTEGER(5);
  Ename VARCHAR2(50);
  Zdjecie BLOB);
 
DECLARE
  b BLOB;
  f BFILE;
BEGIN
  INSERT INTO Emp VALUES(1, 'Kowalski', Empty_BLOB());
  SELECT Zdjecie INTO b FROM Emp WHERE Empno=1 FOR UPDATE;
  f:=Bfilename('KATALOG','Kowalski.gif');
  DBMS_LOB.Loadfromfile(b,f,DBMS_LOB.Lobmaxsize);
END;
/

Usuwanie obiektów LOB

Nie ma bezpośredniej operacji usuwania obiektu LOB. W celu usunięcia go, można albo usunąć cały wiersz z obiektem, albo zastąpić go w wierszu innym. Najpierw, usunięcie wiersza z obiektem LOB:

DELETE FROM Employee e
WHERE e.Ename = 'Jan Kowalski';
Z kolei, usunięcie obiektu LOB w wierszu:
UPDATE Employee e SET e.Resume = Empty_CLOB()
  WHERE e.Ename = 'Jan Kowalski';

 


Podsumowanie

Zapoznaliśmy się ze sposobem przechowywania w bazie danych i posługiwania się w języku SQL:

Wykład stanowi tylko wprowadzenie do pełnego opanowania przez czytelnika posługiwania się obiektami. Zachęcamy czytelnika do wykonania podanych poniżej zadań domowych oraz przestudiowania dokumentacji Oracle: Application Developer's Guide - Object-Relational Features i Application Developer's Guide - Large Objects (LOBs).

Rodzi się naturalne pytanie. Czy lepiej konstruować relacyjne czy relacyjno-obiektowe bazy danych? 

Skoro więc trapią nas wątpliwości, który rodzaj baz danych wybrać, może wybierzemy trzeci rodzaj baz danych, które właśnie na naszych oczach powstają – tzw. bazy XMLowe. Wprowadzenie do nich jest tematem osobnego wykładu.
 


Słownik pojęć

typ obiektowy - definiowany przez użytkownika typ danych, który hermetyzuje strukturę danych łącznie z metodami potrzebnymi do operowania na strukturze danych. Można stosować dziedziczenie własności między typami obiektowymi i ich przesłanianie (powtórne zdefiniowanie w podtypie).

tabela obiektowa - tabela, w której są zapisywane obiekty typu obiektowego na tej samej zasadzie co wiersze tabeli relacyjnej. To znaczy, wartości atrybutów tworzą wiersz, na którym działają metody określone w typie obiektowym.

typ referencyjny - typ wartości reprezentujący odwołania do obiektów w bazie danych. Jest obiektową alternatywą do wiązania tabel przez wartość klucza obcego.

kolekcja - typ wartości w bazie danych reprezentujący zbiory wartości prostych lub obiektów.

duży obiekt LOB - typ wartości w bazie danych reprezentujący duże obiekty w rodzaju dokumentów tekstowych, plików z obrazem, dźwiękiem lub video.

DBMS_LOB - pakiet z operacjami na dużych obiektach LOB.

 


Zadania

  1. Wykonaj kolejno wszystkie przykłady z wykładu.
  2. Zbuduj obiektowo-relacyjną bazę zamówień, w której wszystkie pozycje danego zamówienia znajdują się na liście będącej wartością atrybutu obiektu zamówienia. Przyjmijmy, że maksymalna liczba pozycji na zamówieniu wynosi 20.
  3. Napisz i wykonaj instrukcje INSERT wpisujące przykładowe dane do bazy. Wprowadź co najmniej 2 klientów, co najmniej 5 towarów i co najmniej 4 zamówienia.
  4. Napisz zapytanie które wypisuje wszystkie zamówienia z bazy.
  5. Napisz procedurę PL/SQL, która wypisuje wszystkie zamówienia z bazy - wzorując się na przykładzie dla wydziałów i projektów.
  6. Napisz procedury PL/SQL:


Strona przygotowana przez Lecha Banachowskiego. Ostatnia aktualizacja - 03/10/05