
Strona o szybkim czytaniu.
Typ rekordowy grupuje w sobie pewną ilość powiązanych logicznie ze sobą zmiennych. Świetnie nadaje się do odwzorowania jednego wiersza tabeli w kodzie PL/SQL.
TYPE typ_rekordowy IS RECORD (
zmienna1 typ1,
zmienna2 typ2
...
)
DECLARE
TYPE t_osoba IS RECORD (
nazwisko varchar2(64) NOT NULL,
imie varchar2(40) NOT NULL,
data_ur date);
v_ojciec t_osoba;
v_matka t_osoba;
BEGIN
...
Inna metoda deklaracji zmiennej rekordowej polega na referencji do istniejącej zmiennej lub do tabeli:
zmienna tabela%ROWTYPE;
Dostęp do pól rekordu uzyskuje się przy pomocy notacji kropkowej.
Nie można użyć zmiennej rekordowej bezpośrednio po słowie kluczowym VALUES
w instrukcji INSERT
, ani po słowie INTO
w instrukcji SELECT
.
towary
. Następnie wczytać do tej zmiennej informacje o towarze "Szafka".
DECLARE
v_tow towary%ROWTYPE;
BEGIN
SELECT tow_id, tow_nazwa, tow_jednostka, tow_cena, tow_podatek, tow_tow_id
INTO v_tow.tow_id, v_tow.tow_nazwa, v_tow.tow_jednostka, v_tow.tow_cena, v_tow.tow_podatek, v_tow.tow_tow_id
FROM towary
WHERE tow_nazwa = 'Szafka';
...
Zmienne typu tablicowego przechowują szereg wartości innego, jednorodnego typu w postaci ciągu pojedynczych elementów. Do poszczególnych pozycji w zmiennej tablicowej uzyskujemy dostęp poprzez podanie nazwy tej zmiennej i numeru pozycji (indeksu) dla konkretnego elementu.
TYPE typ_tablicowy IS TABLE OF typ_składowy
INDEX BY BINARY_INTEGER
Zmienne typu tablicowego w PL/SQL nie mają ograniczonej wielkości, można do nich wkładać elementy na dowolnej pozycji z zakresu liczb binary_integer
.
Dopiero przypisanie wartości do jakiegoś elementu tablicy tworzy ten element.
Odwołania do poszczególnych pozycji tablicy odbywają się poprzez podanie indeksu w okrągłych nawiasach.
DECLARE
TYPE t_nazwiska IS TABLE OF varchar2(100)
INDEX by binary_integer;
v_nazwiska t_nazwiska;
v1 varchar2(100);
BEGIN
v_nazwiska(0) := ‘Kowalski’;
v_nazwiska(1000) := ‘NOWAK’;
v_nazwiska(-157230) := ‘Misiak’;
v_1 := v_nazwiska(1000);
...
Zmienne tablicowe posiadają szereg atrybutów, które pozwalają łatwiej operować na ich zawartości. Poniżej zostały one pokrótce scharakteryzowane.
EXIST(n)
– Sprawdza, czy na pozycji n w tablicy znajduje się jakiś element. Zwraca TRUE lub FALSE.COUNT
– Zwraca ilość elementów znajdujących się w tablicy.FIRST
, LAST
– Zwracają indeks pierwszego i ostatniego elementu w tablicy.NEXT(n)
, PRIOR(n)
– Zwracają indeks następnego i poprzedniego elementu w tablicy, względem zadanej pozycji n.DELETE
, DELETE(n)
, DELETE(m,n)
– usuwa elementy z tablicy. W zależności od parametrów usuwa całą tablicę, n-ty element, lub elementy od m do n.
CREATE OR REPLACE FUNCTION modyfikuj_tablice RETURN number
IS
TYPE t_liczby IS TABLE OF number
INDEX BY BINARY_INTEGER; -- definicja typu
v_liczby_tab t_liczby; -- deklaracja zmiennej tablicowej
v_index binary_integer; -- deklaracja zmiennych pomocniczych
v_koniec binary_integer;
BEGIN
-- wywołanie hipotetycznej procedury, która inicjalizuje
-- tablice wstawiajc tam w dowolny sposób dowolna ilość liczb,
-- np. przeczytanych z pliku lub tabeli bazodanowej
tab_init(v_liczby_tab);
-- znalezienie najmniejszego indeksu zajętego w tablicy
v_index := v_liczby_tab.FIRST;
-- znalezienie największego indeksu zajętego w tablicy
v_koniec := v_liczby_tab.LAST;
-- przetwarzanie wszystkich elementów zawartych w tablicy
LOOP
-- wykonanie operacji
IF v_liczby_tab(v_index) > 1000 THEN
v_liczby_tab.DELETE(v_index);
ELSIF v_liczby_tab(v_index) < 0 THEN
v_liczby_tab(v_index) := 0;
END IF;
-- jeżeli przetworzylimy ostatni element, to koczymy pętlę
EXIT WHEN v_index = v_koniec;
-- znalezienie indeksu kolejnego elementu
v_index := v_liczby_tab.NEXT(v_index);
END LOOP;
-- zwrócenie ilości elementów w przetworzonej tablicy
RETURN v_liczby_tab.COUNT;
END;
Kursory są konstrukcją PL/SQL służącą do sekwencyjnego przetwarzania zbioru wielu wierszy zwróconych przez zapytanie z bazy danych.
Przetwarzanie każdego kursora można podzielić na cztery etapy:
Kursory deklaruje się w sekcji deklaracyjnej bloku PL/SQL.
DECLARE
CURSOR nazwa_kursora IS
wyrażenie_select;
BEGIN
wyrażenie_select
jest to dowolne zapytanie zwracające pewną ilość kolumn i wierszy.
Otwarcia kursora dokonujemy w sekcji wykonywalnej bloku PL/SQL. Ten sam kursor może być otwarty tylko jeden raz.
OPEN nazwa_kursora;
Przetworzenie wszystkich danych (lub niekoniecznie wszystkich) wybranych przez zapytanie odbywa się poprzez sekwencyjne wywoływanie instrukcji FETCH
.
FETCH nazwa_kursora INTO lista_zmiennych;
Każda kolejna instrukcja FETCH
ściąga jeden, kolejny wiersz ze zbioru utworzonego przez zapytanie. Każdy wiersz jest ściągnięty tylko jeden raz i nie ma możliwości powtórnego ściągnięcia tego samego wiersza.
Zamknięcie kursora powoduje zwolnienie zasobów zarezerwowanych na jego otwarcie. Kursor przestaje być dostępny i może być ponownie otworzony.
CLOSE nazwa_kursora;
Atrybuty kursora opisują pewne jego cechy i mogą być wykorzystane np. do określenia, kiedy należy zaprzestać pobierania kolejnych wierszy.
Do atrybutów kursora odwołujemy się w następujący sposób:
nazwa_kursora%nazwa_atrybutu
Istnieją cztery atrybuty kursora:
FOUND
– Zwraca TRUE, jeśli ostatnio wykonana komenda FETCH
zwróciła wiersz, w przeciwnym wypadku FALSE. Jeżeli kursor jest nie otwarty, odwołanie się powoduje błąd ORA-01001 i zgłoszenie wyjątku: invalid_cursorNOTFOUND
– Zwraca TRUE, jeśli ostatnio wykonana komenda FETCH
nie zwróciła już poprawnego wiersza, w przeciwnym wypadku FALSE. Jeżeli kursor jest nie otwarty, odwołanie się powoduje błąd ORA-01001 i zgłoszenie wyjątku: invalid_cursorISOPEN
– Zwraca TRUE bądź FALSE w zależności od tego, czy kursor jest zamknięty, czy otwarty.ROWCOUNT
– Zwraca ilość wierszy już ściągniętych z kursora.
CREATE OR REPLACE FUNCTION opisy RETURN varchar2
IS
CURSOR c_opisy IS
SELECT zam_opis
FROM zamowienia
WHERE zam_data_realizacji IS NULL;
v_napis varchar2(32760);
v_opis zamowienia.zam_opis%TYPE;
BEGIN
OPEN c_opisy;
LOOP
FETCH c_opisy INTO v_opis;
EXIT WHEN c_opisy%NOTFOUND;
v_napis := v_napis || v_opis || ' $^$ ';
END LOOP;
CLOSE c_opisy;
RETURN substr(v_napis, 1, length(v_napis)-3);
END;
Przetwarzanie kursorów można uprościć dzięki tzw. pętlom kursorowym.
FOR zmienna_kursorowa IN nazwa_kursora LOOP
ciąg_instrukcji
END LOOP;
Zmienna zmienna_kursorowa
jest zmienną typu rekordowego. Nie powinna być deklarowana.
Stosując pętle kursorowe nie trzeba pamiętać o otwieraniu, ściąganiu i zamykaniu kursora. Pętla wykona się tyle razy, ile wierszy zostanie znalezionych przez zapytanie kursora, a przy każdym wykonaniu się pętli zmienna_kursorowa
będzie zawierać kolejny wiersz zwrócony z zapytania.
CREATE OR REPLACE FUNCTION opisy RETURN varchar2
IS
CURSOR c_opisy IS
SELECT zam_opis
FROM zamowienia
WHERE zam_data_realizacji IS NULL;
v_napis varchar2(32760);
BEGIN
FOR zamowienie IN c_opisy LOOP
v_napis := v_napis || zamowienie.zam_opis || ' $^$ ';
END LOOP;
RETURN substr(v_napis, 1, length(v_napis)-3);
END;
Kursory można parametryzować poprzez zmienne lub poprzez parametry.
Zakres wierszy obejmowanych przez kursor można uzależnić od pewnego parametru odwołując się przy deklaracji kursora w klauzuli WHERE
zapytania do pewnej zadeklarowanej wcześniej zmiennej.
W czasie wykonywania się bloku zmienna ta może przybierać różne wartości, a zatem kursor będzie definiowany przez inne zapytanie.
DECLARE
v1 klienci.klt_typ%TYPE;
CURSOR c_klt IS
SELECT * FROM klienci WHERE klt_typ = v1;
BEGIN
v1 := ‘IND’;
OPEN c_klt;
...
v1 := ‘GSP’;
OPEN c_klt;
...
END;
Ten sposób parametryzacji jest bardziej czytelny i polega na zdefiniowaniu parametrów formalnych podczas deklarowania kursora, a następnie wprowadzeniu parametrów aktualnych podczas otwierania tego kursora.
DECLARE
CURSOR nazwa_kursora(parametr1 typ1{, parametr2 typ2}) IS
wyrażenie_select
BEGIN
OPEN nazwa_kursora(wartość1{,wartość2});
...
END;
DECLARE
CURSOR c_klt(cup_typ varchar2) IS
SELECT * FROM klienci WHERE klt_typ = cup_typ;
BEGIN
OPEN c_klt(‘IND’);
...
OPEN c_klt(‘GSP’);
...
END;