Spis treści
Wstęp
Literatura
ORACLE SQL Language Reference Manual
ORACLE PL/SQL User's Guide and Reference
ORACLE SQL*Plus User's Guide and Reference
Oracle9i Database Online Documentation
Wymagane oprogramowanie
System operacyjny: MS Windows NT4 / 2000 / XP
Baza danych: Oracle 8i / 9i
Edytor PL/SQL: PL/SQL Developer / SQL Navigator / inny analogiczny
Wprowadzenie
SQL - Structured Query Language - strukturalny język zapytań. Jest językiem unormowanym przez ANSI i ISO.
PL/SQL jest rozszerzeniem proceduralnym do języka SQL opracowanym przez Oracle. Może korzystać z większości poleceń SQL.
Środowisko uruchomieniowe PL/SQL może być zainstalowane na serwerze jak i w aplikacji developerskiej.
Motor PL/SQL akceptuje na wejściu bloki PL/SQL-owe. Przetwarza polecenie proceduralne natomiast polecenia SQL-owe przesyła na serwer.
Grupy poleceń należących do języka SQL:
DDL - Data Definition Language - służy do definiowania struktury danych;
DML - Data Manipulation Language - umożliwia zmianę danych w bazie danych;
DCL - Data Control Language - umożliwia sterowanie transakcjami;
Query Language - język wykonywania zapytań, czyli pobierania danych z bazy.
Tworzenie bazy danych
Utworzenie skryptów generujących bazę danych - proces tworzenia bazy, ale na końcu zamiast tworzyć bazę wygenerować skrypty. Analiza utworzonych skryptów.
Pliki składające się na bazę danych i wykorzystywane podczas jej obsługi:
Pliki kodu (code files) - zawierają oprogramowanie systemu zarządzania bazą danych: wykorzystywane do administrowania bazą, tworzenia bazy i inne. Pliki kodu znajdują się w podkatalogach katalogu domowego Oracle: dbs, bin, rdbms.
Pliki danych (data files) - przechowują dane systemowe i dane użytkownika. Zgodnie z konwencją posiadają rozszerzenie dbf.
Pliki dziennika powtórzeń (redo log files) - rejestrują operacje wykonywane na bazie danych. Wykorzystywane do odtwarzania bazy danych po awarii. Zgodnie z konwencją aktywne pliki dziennika powtórzeń (online redo log files) posiadają rozszerzenia log, a zarchiwizowane (archived redo log files) - arc.
Pliki kontrolne (control files) - zawierają informacje o bazie danych: nazwy i położenie plików danych, plików dziennika powtórzeń, dostępność poszczególnych plików, dane wykorzystywane podczas odtwarzania bazy danych po awarii. Zgodnie z konwencją pliki te posiadają rozszerzenia ctl.
Pliki konfiguracyjne (init files) - zawierają parametry konfiguracyjne bazy danych, odczytywane w czasie uruchamiania bazy. Pliki te posiadają nazwy init<SID>.ora, gdzie <SID> oznacza nazwę instancji bazy danych, np. initbaza.ora.
Użytkownik i prawa
Użytkownik, schemat
Tworzenie użytkownika:
CREATE USER użytkownik IDENTIFIED BY hasło;
Zmian parametrów użytkownika (np. hasła):
ALTER USER użytkownik IDENTIFIED BY hasło;
Usunięcie użytkownika:
DROP USER użytkownik [CASCADE];
Z każdym użytkownikiem bazy tworzony jest jego schemat, czyli zbiór obiektów należących do użytkownika. Do schematu mogą należeć następujące typy obiektów:
tabela (table) - obiekt, w której fizycznie przechowywane są dane
prespektywy (view) - definiowana prezentacja pobierana z tabel lub innych prespektyw
sekwencja (sequence) - generatory kolejnych liczb zapewniające unikalność numerów przy dostępie równoległym
symonim (synonym) - aliasy (alternatywne nazwy) do innych obiektów w bazie
indeksy (index) - struktury związane z tabelami, mają na celu przyspieszenie wykonywania zapytań
procedura (procedure) - składowane w bazie danych fragmenty kodu, nie zwracają wyniku
funkcja (function) - składowane w bazie danych fragmenty kodu, zwracają wynik
pakiet (package) - składowane w bazie danych fragmenty kodu, zbiory procedur i funkcji
wyzwalacz (trigger) - programy składowane w bazie, uruchamiane automatycznie w momencie wystąpienia określonego zdarzenia
inne
Dodatkowo aby tworzyć własne obiekty użytkownik musi posiadać prawa do przestrzeni tabel.
Nadanie praw do tworzenia obiektów w przestrzeni tabel:
ALTER USER użytkownik
QUOTA UNLIMITED ON przestrzeń_tabel;
Prawa
Aby użytkownik mógł cokolwiek wykonać musi posiadać stosowne prawa.
Prawa można podzielić na:
prawa systemowe - prawo do wykonania określonej akcji (oznacza to prawa do wykonania poleceń ALTER, CREATE, DROP, GRANT i inne) lub do wykonania akcji na obiekcie określonego typu w dowolnym schemacie (np. SELECT ANY TABLES);
prawa obiektowe - prawo do wykonania akcji na wskazanym obiekcie; mają znaczenie jeżeli użytkownik nie posiada prawa systemowego ANY do danego typu obiektu;
Rodzaj prawa obiektowego |
Typ obiektu |
|||
|
TABELA |
PERSPEKTYWA |
SEKWENCJA |
PROCEDURA FUNKCJA PAKIET |
SELECT |
X |
X |
X |
|
INSERT |
X |
X |
|
|
UPDATE |
X |
X |
|
|
DELETE |
X |
X |
|
|
ALTER |
X |
|
X |
|
EXECUTE |
|
|
|
X |
INDEX |
X |
|
|
|
REFERENCES |
X |
|
|
|
Nadawanie praw:
GRANT prawo_systemowe TO użytkownik;
GRANT prawo_do_obiektu obiekt TO użytkownik;
Na przykład:
GRANT
CREATE SESSION,
CREATE TABLE,
CREATE VIEW,
CREATE TRIGGER,
CREATE PROCEDURE,
CREATE SEQUENCE
TO użytkownik;
GRANT CREATE PUBLIC SYNONYM TO użytkownik;
Możliwe jest nadanie praw wszystkim użytkownikom:
GRANT prawo TO PUBLIC;
Role
Role to nazwa grupy praw, która może być przydzielona użytkownikowi lub innej roli.
Role ułatwiają administrowanie prawami.
Nadawanie ról:
GRANT rola TO użytkownik;
Istnieją role predefiniowanie:
CONNECT - prawo łączenia się do bazy i tworzenia obiektów;
RESOURCE - prawo tworzenia klastrów, procedur, sekwencji, tabel i triggerów;
DBA - wszystkie uprawnienia systemowe;
GRANT CONNECT, RESOURCE TO użytkownik; -- pozwala nadać większość potrzebnych praw nowemu użytkownikowi
Odebranie praw
REVOKE prawo_systemowe FROM użytkownik;
REVOKE rola FROM użytkownik;
REVOKE prawo_do_obiektu obiekt FROM użytkownik;
Typy danych
NUMBER(ilość_znaków, skala) |
Zmienna liczbowa (dziesiętna) ilość_znaków = łączna liczba cyfr znaczących; od 1 do 38 skala = liczba cyfr po prawej stronie znaku dziesiętnego; od -84 do 127 Domyślnie przyjmowane są maksymalne wartości ilość_znaków i skala. |
BINARY_INTEGER |
Zmienna liczbowa (całkowita) od -2^31 do 2^31 |
VARCHAR2(rozmiar) |
Zmienna ilość znaków, maksymalnie < rozmiar > znaków |
CHAR(rozmiar) |
Stała ilość <rozmiar> znaków |
LONG |
Ciągi znaków do 2 GB (231 -1 bajtów) Przestarzały typ, preferowana zmiana na typ LOB |
DATE |
Data od 01-01-4712 BC do 31-12-9999 AD Zawiera zarówno datę jak i czas z dokładnością |
CLOB |
character large object - zmienna typu LOB, zapisywana w trybie znakowym do 4 GB |
BLOB |
binary large object - zmienna typu LOB, zapisywana w trybie binarnym do 4 GB |
BOOLEAN |
wartość logiczna, przyjmuje jedną z wartości: TRUE, FALSE, NULL |
Konwersja typów
Z typu |
Do typu |
||
|
char |
number |
date |
char |
|
TO_NUMBER( tekst [, format]) |
TO_DATE (tekst [, format]) |
number |
TO_CHAR (numer [, format]) |
|
TO_DATE (numer, `J') |
date |
TO_CHAR (data [, format]) |
niemożliwa |
|
Format liczb
Format |
Opis |
9 |
Cyfra nieobowiązkowa |
0 |
Cyfra obowiązkowa |
. |
Kropka dziesiętna |
, |
Przecinek dziesiętny |
MI |
Znak minus z prawej strony (dla wartości ujemnych) |
D |
Domyślny znak dziesiętny |
G |
Domyślny separator tysięcy |
Format zapisu daty i czasu
Format |
Opis |
SCC lub CC |
Wiek. Jeśli użyto S, to daty ujemne są poprzedzone przez BC |
YYYY lub SYYYY |
Rok. Jeśli użyto S, to daty ujemne są poprzedzone przez BC Zamiennie można użyć liter `R' |
YYY lub YY lub Y |
Ostatnie 3, 2, 1 cyfry roku |
IYYY, IYY, IY, I |
4-, 3-, 2-, 1- cyfrowy rok zgodnie ze standardem ISO |
SYEAR lub YEAR |
Rok słownie. Jeśli użyto S, to daty ujemne są poprzedzone przez BC |
BC lub AD |
Oznacznik BC/AD |
Q |
Kwartał roku |
MM |
Miesiąc dwucyfrowo |
MONTH |
Nazwa miesiąca uzupełniona odstępami do dziewięciu znaków |
MON |
Trzyliterowy skrót nazwy miesiąca |
RM |
Miesiąc cyframi rzymskimi |
WW lub W |
Tydzień roku lub miesiąca |
DDD, DD lub D |
Dzień roku, miesiąca lub tygodnia |
DAY |
Nazwa dnia tygodnia uzupełniona odstępami do dziewięciu znaków |
DY |
Trzyliterowy skrót nazwy dnia tygodnia |
J |
Dzień wg kalendarz juliańskiego; liczba dni do 31-12-4713 p.n.e. |
HH, HH12 lub HH24 |
Godzina dnia: wg lokalnych ustawien, 1-12, lub 0-23 |
MI |
Minuta (0-59) |
SS |
Sekunda (0-59) |
SSSSS |
Liczba sekund od północy (0-86399) |
Przykłady:
select ... from dual; |
wynik |
to_number('10,25') |
liczba: 10,25 |
to_number('10.25','99.99') |
liczba: 10,25 |
to_date('01-01-2005','DD-MM-YYYY') |
data: 01-01-2005 |
to_date(2453471,'J') |
data: 10-04-2005 |
to_char(123.40) |
tekst: `123,4' |
to_char(123.40,'0999.00') |
tekst: `0123.40' |
to_char(123456.78,'999G999D00') |
tekst: `123.456,78' |
to_char(sysdate,'DD-MM-RRRR DAY HH24:MI:SS') |
tekst: `10-04-2005 CZWARTEK 23:15:34' |
Funkcje SQL
Funkcja |
Opis |
Przykład |
Funkcje znakowe |
||
CHR(numer) |
Znak o podanym kodzie |
CHR(65) = `A' |
ASCII(tekst) |
Zwraca kod ASCII pierwszej litery w podanym ciągu znaków |
ASCII(`A') = 65 |
LENGTH(tekst) |
Długość tekstu (liczba znaków) |
LENGTH(`aaa') = 3 |
LOWER(tekst) |
Zamienia znaki na małe |
LOWER(`AbC') = `abc' |
UPPER(tekst) |
Zamienia znaki na duże |
UPPER(`AbC') = `ABC' |
INITCAP(tekst) |
Pierwszą literę w wyrazie zamienia na dużą a pozostałe na małe |
INITCAP(`AlA Ma KOTa') = `Ala Ma Kota' |
LPAD(tekst,n,uzup) |
Uzupełnia tekst z lewej strony do n znaków tekstem uzup |
LPAD(`aaa',5,'X') = `XXaaa' |
RPAD(tekst,n,uzup) |
Uzupełnia tekst z prawej strony do n znaków tekstem uzup |
RPAD(`aaa',5,'X') = `aaaXX' |
RTRIM(tekst [,zbior]) |
Usuwa z tekstu od prawej strony wszystkie znaki aż do napotkania znaku niewymienionego w zbior. Jeżeli nie zostanie podany zbiór, to usuwane są wszystkie spacje. |
RTRIM(`cdecaba','ab') = `cdec' RTRIM(`aaa ') = `aaa' |
LTRIM(tekst [,zbior]) |
Usuwa z tekstu od lewej strony wszystkie znaki aż do napotkania znaku niewymienionego w zbior. Jeżeli nie zostanie podany zbiór, to usuwane są wszystkie spacje. |
LTRIM(`aabcdec','ab') = `cdec' LTRIM(` aaa') = `aaa' |
REPLACE(tekst,t_z,t_na) |
Zamienia w tekst wszystkie wystąpienia ciągów t_z na ciągi t_na |
REPLACE(`xx / xx = 1','xx','22') = '22 / 22 = 1' |
SUBSTR(tekst, m [,n]) |
Przekazuje n znaków z ciągu tekst począwszy od pozycji m (włącznie). Jeśli n pominięto, przekazywane są wszystkie znaki od pozycji m. |
SUBSTR(`abcdef',3,2) = `cd' SUBSTR(`abcdef',3) = `cdef' SUBSTR(`abcdef',-3,2) = `de' |
INSTR( tekst1, tekst2, [,n [,m]] ) |
Zwraca pozycję m-tego wystąpienia tekst2 w tekst1, jeżeli szukanie rozpoczęto od pozycji n. Domyślnie n = 1 (szukanie od początku) Domyślnie m = 1 (szukanie pierwszego wystąpienia) |
INSTR(`abcdc','c') = 3 INSTR(`abcdc','c',4) = 5 INSTR(`abcdc','c',1,2) = 5 |
Funkcje na datach |
||
data + liczba data - liczba |
Dodaje / odejmuje do / od daty podaną liczbę dni |
'01-01-2005' - 1 = '31-12-2004' |
data - data |
Przekazuje liczbę dni od pierwszej daty do drugiej daty |
'09-01-2005' - '01-01-2005' = 9 |
MONTHS_BETWEEN(d1, d2) |
Przekazuje liczbę miesięcy między d1 i d2. Wynik może być dodatni albo ujemny. Wynik nie musi być liczbą całkowitą. Ułamek odpowiada części miesiąca. |
MONTHS_BETWEEN ('01-01-2005','10-04-2005') = -3,29032258064516 |
ADD_MONTHS(data, n) |
Dodaje n kalendarzowych miesięcy do daty. Liczba n musi być całkowita, ale może być ujemna. |
ADD_MONTHS('31-01-2005',1) = '28-02-2005' |
NEXT_DAY(data, 'znak') |
Znajduje następny dzień po dacie, który jest dniem tygodnia wskazanym przez 'znak'. 'znak' może być liczbą lub nazwą dnia tygodnia. |
NEXT_DAY('10-04-2005','NIEDZIELA') = '17-04-2005' |
LAST_DAY(data) |
Znajduje datę ostatniego dnia miesiąca zawierającego datę. |
LAST_DAY('10-04-2005') = '30-04-2005' |
ROUND(data[,'fmt']) |
Przekazuje zaokrąglenie daty do jednostki określonej przez model formatu 'fmt'. Jeśli nie podano 'fmt' zaokrąglenie następuje do najbliższej pełnej daty. |
ROUND( to_date('20-04-2005','DD-MM-RRRR'), 'MM') = '01-05-2005' |
TRUNC(data[, 'fmt']) |
Przekazuje obcięcie daty do jednostki określonej przez model formatu 'fmt'. Jeśli nie podano 'fmt' obcięcie nastepuje do najbliższej pełnej daty. |
TRUNC( to_date('20-04-2005','DD-MM-RRRR'), 'MM') = '01-04-2005' |
SYSDATE |
Zwraca aktualną datę i czas |
|
Funkcje numeryczne |
||
ABS(n) |
Zwraca wartość bezwzględną |
ABS(-1) = 1 |
CEIL(n) |
Zwraca najmniejszą liczbę całkowitą większą lub równą n |
CEIL(4.8) = 5 |
FLOOR(n) |
Zwraca największą liczbę całkowitą mniejszą lub równą n |
FLOOR(4.8) = 4 |
MOD(m, n) |
Przekazuje resztę z dzielenia m przez n |
MOD(5, 2) = 1 |
POWER(m, n) |
Podnosi m do potęgi n |
POWER(3, 4) = 81 |
SQRT(n) |
Pierwiastek kwadratowy z liczby n |
SQRT(9) = 3 |
ROUND(e, [n]) |
Przekazuje zaokrąglenie e do n miejsc po przecinku. |
ROUND(16.89) = 17 ROUND(16.89,1) = 16,9 ROUND(16.89,-1) = 20 |
TRUNC(e, [n]) |
Przekazuje obcięcie e do n miejsc po przecinku. |
TRUNC(16.89) = 16 TRUNC (16.89,1) = 16,8 TRUNC (16.89,-1) = 10 |
SIGN(n) |
Zwraca 0 jeżeli n jest równe 0. Zwraca -1 jeżeli n jest mniejsze od 0. Zwraca 1 jeżeli n jest większe od 0. |
SIGN(-10) = -1 |
Funkcje inne |
||
NVL(x, y) |
Jeśli x nie jest NULL, to przekazuje x. |
NVL(10,1) = 10 NVL(null, `aaa') = `aaa' |
DECODE(e, s1, r1 [, s2, r2,...,] [, defautl]) |
Jeśli e = s1, to przekazuje r1. |
DECODE(`x','a',1,'x',2,3) = 2 DECODE(`b','a',1,'x',2,3) = 3 |
GREATEST(x1 [,x2]...) |
Wybiera największą wartość z x1, x2, ... |
GREATEST(10,9,12) = 12 |
LEAST(x1 [,x2]...) |
Wybiera najmniejszą wartość z x1, x2, ... |
LEAST(10,9,12) = 9 |
USER |
Zwraca nazwę użytkownika |
|
Logika trójwartościowa
Wyrażenie: wynik = NOT <wartość>
Wynik |
Wartość |
||
|
TRUE |
FALSE |
UNKNOWN |
|
FALSE |
TRUE |
UNKNOWN |
Wyrażenie: wynik = <wartość1> AND <wartość2>
Wynik |
Wartość1 |
|||
|
TRUE |
FALSE |
UNKNOWN |
|
Wartość2 |
TRUE |
TRUE |
FALSE |
UNKNOWN |
|
FALSE |
FALSE |
FALSE |
FALSE |
|
UNKNOWN |
UNKNOWN |
FALSE |
UNKNOWN |
Wyrażenie: wynik = <wartość1> OR <wartość2>
Wynik |
Wartość1 |
|||
|
TRUE |
FALSE |
UNKNOWN |
|
Wartość2 |
TRUE |
TRUE |
TRUE |
U TRUE |
|
FALSE |
TRUE |
FALSE |
UNKNOWN |
|
UNKNOWN |
TRUE |
UNKNOWN |
UNKNOWN |
Obiekty bazy danych (elementy DDL)
Tabela (table)
Tabela to obiekt, w którym fizycznie przechowywane są dane.
Informacje o tabelach w bazie mogą zostać odczytane z perspektyw:
DBS_TABLES (wszystkie tabele)
ALL_TABLES (tabele dostępne dla użytkownika)
USER_TABLES (tabele należące do użytkownika).
Tworzenie:
CREATE TABLE [schemat.]tabela
({kolumna typ [DEFAULT wyrażenie] [table_constraint]} [,{...}])
[własności_fizyczne_tabeli]
[inne_własności_tabeli]
;
schemat |
schemat, w którym zostanie utworzona tabela, określa właściciela tabeli, domyślnie schemat, do którego należy użytkownik tworzący tabelę |
tabela |
Nazwa tworzonej tabeli |
kolumna |
Nazwa kolumny |
typ |
typ danych w kolumnie |
wyrażenie |
Domyślna wartość pola w kolumnie, ustawiana jeżeli podczas wstawiania rekordu do tabeli wartości dla danej kolumny nie zostanie określona. |
table_constraint |
ograniczenie na wartości w kolumnie, przykłady: NOT NULL UNIQUE PRIMARY KEY CHECK (wyrażenie) ... |
własności_fizyczne_tabeli |
informacje o położeniu tabeli w plikach bazy danych, sposobie rozszerzania przestrzeni dla tabeli, ... |
inne_własności_tabeli |
pozostałe właściwości tabeli między innymi treść zapytania, którego wynikiem można wypełnić zakładaną tabelę |
Przykład:
CREATE TABLE pracownicy(
nr_pracownika NUMBER NOT NULL PRIMARY KEY,
imie CHAR(15) NOT NULL CHECK (imie = UPPER(imie)),
nazwisko CHAR(25) NOT NULL CHECK (nazwisko = UPPER(nazwisko)),
nr_wydzialu NUMBER (3) NOT NULL
);
Usuwanie tabeli:
DROP TABLE [schemat.]tabela [CASCADE CONSTRAINTS];
Zmiana tabeli:
Umożliwia zmianę parametrów tabeli
ALTER TABLE [schemat.]tabela
[inne_właściwości_tabeli]
;
pozwala:
zmienić zestaw kolumn;
ADD (kolumna typ ...)
MODIFY (kolumna typ ...)
DROP (kolumna)
RENAME COLUMN stara_nazwa TO nowa nazwa
zmienić zestaw więzów
zmienić parametry fizyczne tabeli
Więzy (constraint)
Więzy dbają o spójność logiczną danych na poziomie bazy danych, niezależnie od kontroli spójności na poziomie aplikacji.
Typy więzów:
NOT NULL constraint (pole wymagalne) - zabezpieczenia aby pole w określonej kolumnie nie było puste;
unique key constraint (klucz unikalny) - zabezpiecza, aby wartości pól w grupie kolumn były unikalne w skali tabeli; wartości pól mogą być puste;
primary key constraint (klucz główny / klucz pierwotny) - połączenie NOT NULL i klucza unikalnego; każda tabela może mieć tylko jeden klucz główny;
foreign key constraint (klucz obcy) - zabezpiecza aby wartość pola w kolumnie występowała również w kolumnie w innej tabeli;
check constraint (sprawdzenie wartości pola) - zabezpiecza aby wartość pola spełniała określone zależności.
Zmiana zestawu więzów:
ALTER TABLE [schemat.]tabela
{ ADD CONSTRAINT nazwa definicja [ENABLE | DISABLE] [USING INDEX]
| MODIFY CONSTRAINT nazwa [ENABLE | DISABLE] [USING INDEX]
| RENAME CONSTRAINT stara_nazwa TO nowa_nazwa
| DROP CONSTRAINT nazwa [CASCADE]
};
definicja oznacza:
{ [NOT] NULL
| UNIQUE (kolumny)
| PRIMARY KEY (kolumny)
| FOREIGN KEY (kolumny) REFERENCES tabela (kolumny) [ON DELETE CASCADE]
| CHECK ( warunek )
}
Opcja USING INDEX może być wykorzystana dla klucza głównego i unikalnego.
Prespektywa (view)
Definiowana prezentacja pobierana z tabel lub innych perspektyw.
Tworzenie:
CREATE [OR REPLACE] VIEW [schemat.]perspektywa
AS
SELECT ...;
Usuwanie:
DROP VIEW [schemat.]perspektywa;
Sekwencja (sequence)
Generatory kolejnych liczb zapewniające unikalność numerów przy dostępie równoległym.
Informacje o sekwencjach w bazie mogą zostać odczytane z perspektyw:
ALL_SEQUENCES (sekwencje dostępne dla użytkownika)
USER_ SEQUENCES (sekwencje należące do użytkownika).
CREATE SEQUENCE [schemat.]sekwencja
[INCREMENT BY liczba]
[START WITH wartość_początkowa]
[CYCLE/NOCYCLE];
Odczyt wartości sekwencji realizujemy za pomocą następującego zapytania:
sekwencja.NEXTVAL
Obecną wartość licznika bez zwiększania jego wartości można odczytać następująco:
sekwencja.CURRVAL
Usuwanie: DROP SEQUENCE
Zmiana: ALTER SEQUENCE
Synonim (synonym)
Aliasy (alternatywne nazwy) do innych obiektów w bazie.
Do wykorzystania na przykład aby móc pominąć wskazywanie nazwy schematu przy odwołaniu do tabeli.
Tworzenie:
CREATE [OR REPLACE] [PUBLIC] SYNONYM [schemat.]nazwa FOR [schemat.]obiekt;
Usunięcie:
DROP [PUBLIC] SYNONYM [schemat.]nazwa;
OR REPLACE - powoduje, że polecenie nie spowoduje błędu jeżeli dany synonim już istnieje.
PUBLIC - utowrzony symonim będzie dostępny dla wszystkich użytkowników. W przeciwnym przypadku dostępny jest tylko wewnątrz schematu.
Indeks (index)
Struktury związane z tabelami, mają na celu przyspieszenie wykonywania zapytań. Odbywa się to kosztem obszaru pamięci potrzebnego na zapamiętanie indeksów oraz spowolnienia modyfikacji danych w indeksowanych kolumnach.
CREATE [UNIQUE] INDEX [schemat.]indeks
ON [schemat.]tabela (atrybut [,…])
[NOSORT]
[własności fizyczne indeksu]
;
UNIQUE - wymusza unikalność wartości w kolumnie, której indeks dotyczy.
NOSORT - wskazuje, że rekordy w tablicy są już posortowane
Informacje o istniejących indeksach przechowywane są w tabelach:
DBA_INDEXES
ALL_INDEXES
USER_INDEXES
DBA_IND_COLUMNS
ALL_IND_COLUMNS
USER_IND_COLUMNS
Procedura (procedure)
Składowane w bazie danych fragmenty kodu, nie zwracają wyniku
CREATE [OR REPLACE] PROCEDURE [schemat.]procedura (p1 IN typ [, ...])
AS
treść;
Funkcja (function)
Składowane w bazie danych fragmenty kodu, zwracają wynik
CREATE [OR REPLACE] FUNCTION [schemat.]funkcja (p1 IN typ [, ...])
RETURN typ_wyniku
AS
treść;
Pakiet (package)
Składowane w bazie danych fragmenty kodu, zbiory procedur i funkcji.
Każda funkcja i procedura wywoływana z pakietu musi być poprzedzona nazwą pakietu i znakiem `.'.
CREATE [OR REPLACE] PACKAGE [schemat.]pakiet
AS
wykaz nagłówków funkcji i procedur;
END pakiet;
CREATE [OR REPLACE] PACKAGE BODY [schemat.]pakiet
AS
wykaz ciał funkcji i procedur;
END pakiet;
Wyzwalacz (trigger)
Programy składowane w bazie, uruchamiane automatycznie w momencie wystąpienia określonego zdarzenia.
Triggery mogą być wywoływane przy okazji zaistnienia zdarzeń typu:
DML (INSERT, UPDATE, DELETE),
DDL (ALTER, CREATE, DROP, GRANT, REVOKE, TRUNCATE, ...)
zdarzeń związanych z bazą danych (SERVERERROR, LOGON, LOGOFF, STARTUP, SHUTDOWN, ...)
Tworzenie triggera dla zdarzeń DML:
CREATE [OR REPLACE] TRIGGER [schemat.]trigger
{BEFORE | AFTER}
{ INSERT
| DELETE
| UPDATE OF kolumna [, ...]
} [OR {...}]
ON [schemat.]tabela
[FOR EACH ROW]
[WHEN (warunek)]
pl/sql_kod
BEFORE |
trigger wywoływany przed wykonaniem zdarzenia |
AFTER |
trigger wywoływany po wykonaniu zdarzenia |
INSERT|DELETE|UPDATE |
rodzaj zdarzenia DML, z którego wykonaniem jest związany trigger; jeden trigger może dotyczyć kilku rodzajów zdarzeń - wtedy zdarzenia łączy się słowem kluczowym OR |
FOR EACH ROW |
określa, że trigger ma być wykonywany dla każdego wiersza |
WHEN |
określa warunek, który musi być spełniony aby został uruchomiony trigger; w warunku można używać słów kluczowych OLD.nazwa_pola i NEW.nazwa_pola odnoszących się starej i nowe wartości wskazanego pola |
pl/sql_kod |
treść kody wykonywanego w triggerze; nie można w nim używać poleceń typu DCL (COMMIT, ROLLBACK, ...); w treści można używać wyrażeń :OLD.nazwa_pola, :NEW.nazwa_pola odwołujące się do starej i nowej wartości pól |
Zapytania (SELECT)
Polecenie SELECT służy do wykonywania zapytań do bazy danych.
Uzyskane dane mogą zostać wykorzystane do:
wyświetlenia na ekran / zapisania do pliku zewnętrzengo;
przypisania do zmiennych w programie;
wstawienia do innej tabeli;
zablokowania danych w bazie danych;
Poza tym polecenie SELECT wykorzystywane jest do:
zdefiniowania perspektyw;
zdefiniowania kursorów w programach PL/SQL;
SELECT definicja_atrybutów_relacji
FROM źródło_danych
[WHERE ograniczenie_selekcji_krotek]
[GROUP BY atrybuty_grupujące [HAVING warunek_na_grupy]]
[ORDER BY uporządkowanie_krotek]
;
SELECT (selekcja atrybutów relacji)
Jako definicja atrybutów relacji możne wystąpić:
znak * - wszystkie kolumny występujące w elementach określonych w źródle danych
select * from wydatki;
specyfikacja atrybutów oddzielonych przecinkami
select data, opis from wydatki;
Jak specyfikacja atrybutów może wystąpić:
nazwa kolumny ze źródła danych;
select data, opis from wydatki;
wartość wyliczona na podstawie:
danych ze źródła,
select trunc(sysdate)-data, opis, kwota*100||' groszy'
from wydatki;
innych funkcji,
select `Dziś mamy:', trunc(sysdate), `Wydatek z dnia:', data, opis
from wydatki;
select sysdate from dual;
select exp(ln(1000)/3) from dual;
innych zapytań
select data, opis, (select opis from osoby where symbol_kto=symbol)
from wydatki;
Definiując atrybuty do pokazania można ograniczyć zakres pokazywanych krotek tylko do wartości nieunikalnych (poprzez słowo kluczowe DISTINCT lub UNIQE):
select DISTINCT(rodzaj)
from wydatki;
Poszczególne specyfikacje atrybutów można nazwać (określić aliasy). Aliasy pokazywane są w wynikach zapytania jako nagłówki kolumn. Aliasy atrybutów mogą być wykorzystane podczas uporządkowania krotek relacji.
select trunc(sysdate)-data jak_dawno, opis, kwota
from wydatki
order by jak_dawno;
ORDER BY (porządkowanie krotek relacji)
Porządkowanie krotek relacji może być wykonywane w oparciu o:
atrybuty relacji wymienione po słowie kluczowym SELECT, jako identyfikator atrybutu można użyć:
pełnej specyfikacji atrybutu
select sysdate-data jak_dawno, opis, kwota
from wydatki
order by sysdate-data;
aliasu atrybutu relacji
select sysdate-data jak_dawno, opis, kwota
from wydatki
order by jak_dawno;
numeru atrybuty
select sysdate-data jak_dawno, opis, kwota
from wydatki
order by 1;
atrybuty relacji nie wymienione po słowie kluczowym SELECT
select sysdate-data jak_dawno, opis, kwota
from wydatki
order by symbol_kto;
Porządkowanie może odbywać się według wielu atrybutów. Można określić kolejność sortowania według każdego z atrybutów oraz określić umiejscowienie krotek o wartości pustej.
ORDER BY
{ atrybut | pozycja_atrybutu | alias_atrybutu }
[ ASC | DESC ]
[ NULLS FIRST | NULLS LAST ]
[, ...]
select sysdate-data jak_dawno, opis, kwota, symbol_kto
from wydatki
order by symbol_kto, jak_dawno desc, 2;
select * from platnosci
order by konto desc nulls last;
WHERE (selekcja krotek relacji)
W celu ograniczenia pokazywanych krotek relacji należy określić warunki jakie musi spełniać krotka, aby została pokazana. Pokazywane są te krotki, dla których zdefiniowany warunek jest prawdziwy. W warunku można odwoływać się do wartości pól dla:
atrybutów relacji wymienione po słowie kluczowym SELECT (nie można użyć aliasów atrybutów relacji)
select sysdate-data jak_dawno, opis, kwota
from wydatki
where sysdate-data > 10;
atrybutów relacji nie wymienione po słowie kluczowym SELECT
select sysdate-data jak_dawno, opis, kwota
from wydatki
where symbol_kto <> symbol_za_kogo;
Budując warunki można wykorzystywać:
operatory matematyczne: `>', `<', `=', `>=', `<=', `<>', `!='
operatory SQL:
[NOT] BETWEEN <wartość_początkowa> AND <wartość_końcowa>
[NOT] IN (<wartość_1> [, wartość_2] [, ...])
[NOT] LIKE <maska>
Maska to ciąg znaków, który jest dopasowywany do wartości pola. W masce wykorzystywane są znaki wieloznaczne:
% - oznacza dowolny ciąg znaków, w tym ciąg pusty
_ - oznacza jeden znak
IS [NOT] NULL
NOT
operatory logiczne łączące wiele warunków prostych w warunek złożony:
AND
OR
W pierwszej kolejności uwzględniany jest operator AND następnie OR.
W ramach warunku można wykonywać podzapytania i następnie odwoływać się do wyników tych zapytań. Takie rozwiązanie ma sens jeżeli w podzapytaniu wykorzystujemy jakiś element krotki z podzapytania nadrzędnego.
Wyniki zapytania podrzędnego można wykorzystać do:
porównania z polem (polami) krotki z zapytania nadrzędnego:
select w.*
from wydatki w
where w.kwota > (select avg(w2.kwota) from wydatki w2);
Można stosować operatory:
matematyczne: `>', `<', `=', `>=', `<=', `<>', `!='
IN - wartość z zapytania nadrzędnego występuje w zapytaniu podrzędnym
<operator matematyczny> ANY - zależność spełniona chociaż dla jednej krotki zapytania podrzędnego
<operator matematyczny> ALL - zależność spełniona chociaż dla jednej krotki zapytania podrzędnego
sprawdzenia czy zapytanie nadrzędne zwraca jakikolwiek dane
Stosowany jest operator [NOT] EXISTS
select w.* from wydatki w
where exists (select * from platnosci p
where w.id_platnosci = p.id and p.konto is not null);
FROM (Określanie źródła danych)
Jako źródło danych można podawać:
tabele
select * from wydatki;
perspektywy
select * from dane;
podzapytania (tymczasowe perspektywy)
select .*
from (select kwota, opis from wydatki) wyd2;
Dla każdego źródła danych można określić alias, przy pomocy którego można rozróżnić źródła w innych elementach zapytania.
select w.opis, w.kwota, p.rodzaj
from wydatki w, platnosci p
where w.id_platnosci = p.id;
Poszczególne źródła oddzielane są przecinkami.
Relacje pomiędzy źródłami określane są poprzez warunek WHERE.
Domyślnie tworzony jest iloczyn kartezjański z obu źródeł:
TAB_1:
ID |
KTO |
1 |
Ala |
2 |
Stefan |
TAB_2:
KTO |
CO |
Ala |
kwiaty |
Stefan |
piwo |
select * from TAB_1 t1, TAB_2 t2;
t1.ID |
t1.KTO |
t2.KTO |
t2.CO |
1 |
Ala |
Ala |
kwiaty |
1 |
Ala |
Stefan |
piwo |
2 |
Stefan |
Ala |
kwiaty |
2 |
Stefan |
Stefan |
piwo |
select * from TAB_1 t1, TAB_2 t2 where t1.KTO = t2.KTO;
t1.ID |
t1.KTO |
t2.KTO |
t2.CO |
1 |
Ala |
Ala |
kwiaty |
2 |
Stefan |
Stefan |
piwo |
Połączenie zewnętrze stosuje się jeżeli w jednym ze źródeł może nie być wartości wiążącej z drugim źródłem, a chcemy pokazać wartości nie powiązane.
select *
from platnosci p, konta k
where p.konto = k.id(+);
(+) stawiamy przy polu ze źródła, w którym nie występuje odpowiednik. W wyniku zapytania zamiast danych z tego źródła pokazane zostaną wartości puste. Czyli pokazujemy wszystko ze źródła bez „plusa” i doczytujemy co nam się uda ze źródła z „plusem”.
GROUP BY (grupowanie krotek)
Grupowanie pozwala na zebranie wielu krotek w oparciu o określone atrybut i wyznaczenie dla danej grupy pewnych wielkości. Dodatkowo słowo kluczowe HAVING pozwala na ograniczenie zapytania tylko do grup spełniających określony warunek.
Jeżeli w zapytaniu użyte są słowa kluczowe ORDER BY, to po SELECT można wymienić:
atrybuty relacji wskazane do grupowania (według których następuje grupowanie)
wyrażenia wyliczone na podstawie pozostałych atrybutów relacji. Dostępne są następujące wyrażenia:
MIN(nazwa_kolumny) - wartość minimalna
MAX(nazwa_kolumny) - wartość maksymalna
SUM(nazwa_kolumny) - suma
AVG(nazwa_kolumny) - średnia
COUNT(nazwa_kolumny) - ilość wierszy z niepustą wartością w kolumnie
COUNT(*) - ilość wierszy, niezależnie od wartości
inne
select rodzaj,
count(*) ilość, avg(kwota) średnio, min(kwota) min, max(kwota) max
from wydatki
group by rodzaj
having count(*)>1;
Łączenie zapytań
Możliwe jest wykonywanie operacji na zbiorach wyników wielu zapytań. Elementami zbioru są krotki zapytań.
Dostępne operacje:
UNION - połączenie zbiorów bez pokazywania duplikatów
UNION ALL - połączenie zbiorów z pokazywaniem duplikatów
INTERSECT - część wspólna zbiorów bez pokazywania duplikatów
MINUS - różnica zbiorów bez pokazywania duplikatów
Aby działania były możliwe typy atrybutów składowych zapytań muszą być takie same.
select 'OPIS_WYDATKU', 'KWOTA' from dual
UNION
select opis, to_char(kwota) from wydatki;
DCL - Data Control Language
Każde polecenie DML powoduje wprowadzanie zmian do bazy i równocześnie zapisanie stanu danych sprzed zmian w odrębnym obszarze bazy nazywanym segmentem wycofania (rollback segment).
Zatwierdzenie transakcji powoduje oznaczenie danych w bazie jako obowiązujących.
Wycofanie zmian, w tym całej transakcji, powoduje przepisanie danych z segmentu wycofania do bazy.
Każde polecenie DDL powoduje automatyczne zatwierdzenie transakcji przed i po swoim wykonaniu, niezależnie od tego czy się powiedzie.
Prawidłowe wylogowanie z bazy powoduje zatwierdzenie transakcji.
Zakończenie sesji bazodanowej na skutek błędu powoduje wycofanie transakcji.
COMMIT
kończy aktualną transakcję i zatwierdza zmiany. Powoduje, że zmiany są widoczne w innych transakcjach.
ROLLBACK
kończy aktualną transackję i wycofuje zmiany wykonane w transakcji
SAVEPOINT
oznaczenie momentu w transakcji, do którego mogą zostać wycofane zmiany
w transakcji można określić określoną liczbę savepointów
ROLLBACK TO SAVEPOINT nazwa_savepoint
wycofuje zmiany wprowadzone od momentu oznaczonego jako savepoint o podanej nazwie
nie kończy transakcji
SET TRANSACTION READ ONLY
musi być wykonane jako pierwsze polecenie w transakcji
oznacza, że w transakcji mogą być wykonane tylko zapytania; system nie pozwoli na wykonanie poleceń DML
DML - Data Manipulation Language
Wstawianie krotek (INSERT)
Polecenie INSERT pozwala na dodanie do tabeli pojedynczego wiersza lub wielu wierszy (uzyskanych w wyniku zapytania).
Podanie pojedynczego wiersza:
INSERT INTO tabela [(columna [, columna] ...)]
VALUES (wyrazenie [,wyrazenie ...])
;
np.:
INSERT INTO rodzaje_wydatkow (rodzaj, opis) VALUES ('X', 'Różne');
Jeżeli nie zostaną podane nazwy kolumn po nazwie tabeli, to system będzie wartości przypisywał do kolumn w kolejności wynikającej z wewnętrznego uporządkowania kolumn. Bezpieczniej i czytelniej jest zawsze wskazywać listę kolumn.
Do nie wymienionych kolumn wstawiane będą wartości NULL.
Dodanie wielu wierszy:
INSERT INTO tabela [(columna [, columna] ...)]
zapytanie
;
create table wydatki_suma
( stan_na date,
dzien date,
kwota number
)
;
insert into wydatki_suma(stan_na, dzien, kwota)
select sysdate, data, sum(kwota) from wydatki
group by data
;
Zmiana wartości pól (UPDATE)
UPDATE tabela
SET kolumna = {wartosc | (zapytania)} [,kolumna = {wartosc | (zapytania)}] ...
WHERE warunek
;
UPDATE tabela
SET (kolumna [, kolumna] ...) = (zapytanie)
WHERE warunek
;
Jeżeli wartość kolumny wyliczana jest na podstawie zapytania, to zapytanie musi zwrócić jeden wiersz. Jeżeli zapytanie nie zwróci żadnego wiersza, to do kolumn zostanie przypisana wartość NULL.
Modyfikowane będą krotki spełniające warunek podany po słownie WHERE.
UPDATE wydatki
SET data = to_date('10-03-2005','DD-MM-RRRR')
WHERE id in (5,6);
UPDATE wydatki w
SET w.opis = w.opis || ' - zmiana',
w.kwota = (SELECT avg(w2.kwota)
FROM wydatki w2
WHERE w2.rodzaj = w.rodzaj)
WHERE w.rodzaj NOT IN ('I')
;
Usuwanie krotek (DELETE)
DELETE FROM tabela
WHERE warunek
;
Polecenie usuwa krotki spełniające warunek podany po słownie WHERE.
Blokowanie krotek (SELECT ... FOR UPDATE)
W wyniku wykonania polecenia DML blokowane są modyfikowane krotki. Ich odblokowanie następuje po zatwierdzeniu lub wycofaniu transakcji.
Zablokowanie krotki może zostać również wykonane poprzez zapytanie (SELECT ...) z klauzulą FOR UPRADE.
zapytanie [FOR UPDATE [{NOWAIT | WAIT ile_sekund}]]
NOWAIT - jeżeli zablokowanie się nie uda, od razu pokazywany jest komunikat od błędzie
WAIT ile_sekund - próbuje zablokować krotki przez podaną ilość sekund. Jeżeli po tym czasie się nie uda, to wyświetla komunikat o błędzie.
Jeżeli żadna z opcji nie zostanie wskazana, to domyślnie system czeka aż zapytanie będzie możliwe (bez ograniczenia czasowego!).
Język PL/SQL
Komentarze:
-- komentarz dotyczący jednej linii
/* komentarz
dotyczący
wieli
linii*/
Struktura programu
Podstawową jednostką programu są bloki.
Struktura bloku:
[DECLARE
deklaracje_zmiennych_stałych_kursorów
]
BEGIN
część_wykonywalna_programu
[EXCEPTION
obsługa_wyjątków
]
END;
Bloki mogą być zagnieżdżone.
W programie PL/SQL mogą być użyte polecenie DML i DCL.
Zmienne, stałe
Typy zmiennych:
proste
numeryczne
znakowe
logiczne
daty
złożone
kolumnowe
wierszowe
rekordowe
tablicowe
Źródło: Dokumentacja ORACLE 9i
Deklaracja zmiennej / stałej:
nazwa_zmiennej typ [CONSTANT] [NOT NULL] [:=wartosc];
CONSTANT - zmienną traktujemy jako stałą
NOT NULL - zmienna nie może mieć wartości pustej
Możliwe jest zadeklarowanie zmiennej, której typ określany na podstawie typów kolumna tabel bazodanowych.
Zmienna wierszowa, przechowująca cały wiersz tabeli:
nazwa_zmiennej tabela%ROWTYPE;
Zmienna, przechowująca pojedyncze pole tabeli:
nazwa_zmiennej tabela.kolumna%TYPE;
Przypisanie wartości zmiennej
poprzez przypisanie wartości wyrażenia:
zmienna := wartosc;
poprzez zapytanie (polecenie SELECT ... INTO ...)
poprzez odczytanie zmiennej z aplikacji zewnętrznej:
:zmienna
poprzez odczytanie zmiennej z aplikacji SQL*Plus:
&zmienna
Polecenie SELECT ... INTO ...
Pozwala odczytać dane z bazy i zapisać ich wartość do zmiennych.
Przykład:
DECLARE
z_kwota number;
z_data date;
BEGIN
SELECT kwota, data
INTO z_kwota, z_data
FROM wydatki
WHERE id = 1;
END;
Zapytanie musi zwrócić jeden wiersz. W przeciwnym przypadku zostanie wywołany jeden z wyjątków:
TOO_MANY_ROWS
NO_DATA_FOUND
Wyświetlenie danych na ekran
Wyświetlanie na ekran:
dbms_output.put_line(tekst);
W aplikacji SQL*Plus konieczne jest dodatkowo wywołanie polecenia:
SET SERVEROUTPUT ON [SIZE rozmiar]
Instrukcja warunkowa (IF)
IF warunek THEN
instrukcje;
[ELSIF warunek THEN
instrukcje; ]
[ELSIF ...]
[ELSE
instrukcje;]
END IF;
Instrukcja CASE
CASE wyrazenie
WHEN wartosc_1 THEN instrukcje_1;
WHEN wartosc_2 THEN instrukcje_2;
[...]
[ELSE instrukcje_else;]
END CASE;
Pętla LOOP
LOOP
[instrukcje;]
{EXIT | EXIT WHEN warunek;}
[instrukcje;]
END LOOP;
Pętla wykonywana jest do momentu natrafienie na polecenie EXIT lub EXIT WHEN ze spełnionym warunkiem przerwania pętli.
Pętla WHILE LOOP
WHILE warunek LOOP
instrukcje;
END LOOP;
Pętla jest wykonywana dopóki warunek jest prawdziwy.
Pętla FOR
FOR licznik IN [REVERSE] dolna_granica..gorna_granica LOOP
instrukcje;
END LOOP;
Instrukcja GOTO
...
GOTO etykieta;
...
<etykieta>
...
Wykorzystanie instrukcji GOTO nie powinno być stosowane nadmiernie. Zawsze można je zastąpić przez inne instrukcje.
Istnieje szereg ograniczeń na miejsce, w które GOTO może przekazywać sterowanie. Nie może spowodować przejścia do fragmentu programu:
wewnątrz instrukcji IF, CASE, LOOP, FOR;
wewnątrz podbloku programu;
na zewnątrz bloku programu, w którym GOTO zostało wywołane;
na zewnątrz bloku EXCEPTION, jeżeli GOTO wywołane wewnątrz tego bloku.
Instrukcja pusta
Czasami przydaje się instrukcja, która nic nie wykonuje. Jest używana tam, gdzie składnia wymaga użycia instrukcji a programista nie chce tam nic wykonywać.
NULL;
np.:
...
EXCEPTION
WHEN ZERO_DIVIDE THEN
ROLLBACK;
WHEN VALUE_ERROR THEN
INSERT INTO errors VALUES ...
COMMIT;
WHEN OTHERS THEN
NULL;
END;
Kursory
Kursor to identyfikator wskazujący na przestrzeń w której przechowywane są wyniki zapytań. Poprzez kursor można odwoływać się tej przestrzeni.
Wyróżniane są kursory:
jawne - deklarowane w kodzie programu
niejawne / domyślny - tworzony automatycznie dla wykonywanych poleceń DML; nie można zarządzać tym kursorem (otwierać, przewijać, zamykać), można natomiast badać jego atrybuty. Nazwa kursora domyślnego to „SQL”.
Kursor jawny musi zostać zadeklarowany. Zadeklarowanie nie powoduje wykonania zapytania. Dzięki temu zapytania mogą być sparametryzowane - uzależnione od innych zmiennych, których wartość jest ustawiana w programie.
Deklaracja:
CURSOR nazwa IS zapytanie;
--kursor bez parametrów
CURSOR nazwa (parametr typ [, ...]) IS zapytanie;
--kursor z parametrami
np.:
CURSOR wydatki_cur IS
select id, data, kwota, opis
from wydatki
where za_kogo = `W'
order by data;
CURSOR wydatki_cur (rodz varchar2) IS
select id, data, kwota, opis
from wydatki
where za_kogo = `W'
and rodzaj = rodz
order by data;
Korzystanie:
Z kursora można korzystać na dwa sposoby:
poprzez pętlę FOR wykonywaną na wierszach kursora;
poprzez własne zarządzenie kursorem: otwarcie (OPEN), odczytanie z przewinięciem rekordu (FETCH) i zamknięciem (CLOSE);
Obsługa poprzez pętlę FOR nie wymaga otwierania i zamykania kursora:
FOR rekord_nazwa IN kursor_nazwa LOOP
. . .
END LOOP;
Przykład:
DECLARE
CURSOR wydatki_cur IS select * from wydatki where rodzaj = 'J';
BEGIN
FOR w_rec IN wydatki_cur LOOP
dbms_output.put_line(w_rec.data||' '|| w_rec.kwota||' '|| w_rec.opis);
END LOOP;
END;
Przy pętli FOR nie jest konieczne deklarowanie kursora jawnego. Można wykorzystać kursor domyślny (o nazwie SQL) i w pętli FOR podać od razu zapytanie:
FOR rekord_nazwa IN (podzapytanie_SQL) LOOP
. . .
END LOOP;
Przykład:
BEGIN
FOR w_rec IN (select * from wydatki where rodzaj = 'J') LOOP
dbms_output.put_line(w_rec.data||' '|| w_rec.kwota||' '|| w_rec.opis);
END LOOP;
END;
Własne zarządzenie kursorem wymaga:
zadeklarowania kursora
otwarcia kursora
OPEN kursor_nazwa;
w dowolnej pętli wykonania odczytania rekordu i zapisania go do zmiennej. Odczytanie rekordu powoduje automatyczne przejście do kolejnego wiersza kursora. Wyjście z pętli powinno nastąpić jeżeli osiągniemy koniec kursora.
FETCH kursor_nazwa INTO zmienna,...; -- odczytanie wiersza
EXIT WHEN kursor_nazwa%NOTFOUND; -- wyjście z pętli
zamknięcia kursora
CLOSE kursor_nazwa;
Przykład 1 (dane z wiersza kursora odczytane do zmiennej wierszowej):
DECLARE
CURSOR wydatki_cur IS select * from wydatki where rodzaj = 'J';
w_rec wydatki%ROWTYPE;
BEGIN
OPEN wydatki_cur;
LOOP
FETCH wydatki_cur INTO w_rec;
EXIT WHEN wydatki_cur %NOTFOUND;
dbms_output.put_line(w_rec.data||' '|| w_rec.kwota||' '|| w_rec.opis);
END LOOP;
CLOSE wydatki_cur;
END;
Przykład 2 (dane z wiersza kursora odczytane do prostych zmiennych):
DECLARE
CURSOR wydatki_cur IS select data, kwota, opis from wydatki where rodzaj = 'J';
r_data wydatki.data%TYPE;
r_kwota wydatki.kwota%TYPE;
r_opis wydatki.opis%TYPE;
BEGIN
OPEN wydatki_cur;
LOOP
FETCH wydatki_cur INTO r_data, r_kwota, r_opis;
EXIT WHEN wydatki_cur %NOTFOUND;
dbms_output.put_line(r_data||' '||r_kwota||' '||r_opis);
END LOOP;
CLOSE wydatki_cur;
END;
Atrybuty kursora:
W trakcie obsługi kursora (domyślnego lub jawnego, niezależnie od metody obsługi) można korzystać z aktrybutów kursora. Wykaz atrybutów:
kursor_nazwa%FOUND |
zwraca TRUE jeżeli udało się odczytanie wiersza z kursora |
kursor_nazwa%NOTFOUND |
zwraca TRUE jeżeli udało się odczytanie wiersza z kursora, np. z powodu osiągnięcia końca kursora |
kursor_nazwa%ISOPEN |
zwraca TRUE jeżeli kursor jest otwarty |
kursor_nazwa%ROWCOUNT |
zwraca liczbę wierszy kursora |
Odczytanie atrybutów kursora domyślnego (SQL) pozwala badać efekty ostatniego wykonanego polecenia DML.
Przykład:
BEGIN
update wydatki set kwota = round(kwota,2) where rodzaj = 'J';
IF SQL%ROWCOUNT >0 THEN
dbms_output.put_line('Zmodyfikowano '||SQL%ROWCOUNT||' wierszy.');
END IF;
END;
Blokowanie przez otwarty kursor
Jeżeli chcemy modyfikować grupę wierszy w bazie, to otwierając kursor można od razu zarezerwować wiersze stanowiące wynik zapytania w kursorze.
DECLARE
CURSOR wydatki_cur IS select * from wydatki where rodzaj = 'J' FOR UPDATE;
w_rec wydatki%ROWTYPE;
i number := 0;
BEGIN
OPEN wydatki_cur;
LOOP
FETCH wydatki_cur INTO w_rec;
EXIT WHEN wydatki_cur %NOTFOUND;
i := i+1;
update wydatki set opis = i||': '||w_rec.opis where CURRENT OF wydatki_cur;
END LOOP;
CLOSE wydatki_cur;
END;
Zmienne kursorowe
Wykorzystywane jeżeli konieczne jest przekazanie otwartego kursora pomiędzy podprogramami.
Deklaracja typu “kursorowego”:
TYPE nazwa_typu_kursorowego IS REF CURSOR RETURN tabela%ROWTYPE;
Wykorzystanie zmiennej typu kursorowego w parametrach wywołania procedury:
PROCEDURE proc_nazwa(zmianna_kursorowa IN OUT nazwa_typu_kursorowego) IS
BEGIN
OPEN zmienna_kursorowa FOR zapytanie;
END proc_nazwa;
Obsługa wyjątków
Wyjątek, to zdarzenie wywołujące błąd występujący w trakcie wykonania programu, który powoduje przerwanie aktualnie wykonywanego polecenia. Mówi się, że „wykonanie polecenia zwróciło błąd / wyjątek”.
Wyróżniane są dwa rodzaje wyjątków:
systemowe - predefiniowane w języku PL/SQL; część z nich ma określone nazwy; system sam je wywołuje w przypadku wystąpienia błędu; programista może je wywołać w kodzie programu;
definiowane przez użytkownika - dodane przez programistę; nazwy określa programista; wywoływane tylko przez programistę.
Przykłady wyjątków systemowych, posiadających nazwy:
CURSOR_ALREADY_OPEN |
powstaje w czasie próby otwarcia kursora już otwartego; np. otwarcie kursora CUR w pętli FOR rekord IN CUR |
INVALID CURSOR |
powstaje w czasie próby wykonania niedozwolonej operacji na kursorze, na przykład zamknięcia kursora nie otwartego |
INVALID_NUMBER |
podanie wartości nie liczbowej tam, gdzie wymagana jest wartość liczbowa, lub liczbowej nie pasującej do zakresu zmiennej |
NO_DATA_FOUND |
jeżeli polecenie DML nie znajduje żadnego wiersza |
TOO_MANY_ROWS |
jeżeli polecenie SELECT INTO zwróci więcej niż jeden wiersz |
VALUE_ERROR |
powstaje z powodu błędów arytmetycznych i konwersyjnych w sytuacjach, których nie obejmuje wyjątek INVALID_NUMBER |
ZERO_DIVIDE |
powstaje przy próbie dzielenia liczby przez zero |
Każdy błąd opisany jest poprzez dwie wartości:
- kod liczbowy; kod ostatniego błędu zapisany jest w zmiennej SQLCODE
- opis - opis błędu zapisany jest w zmiennej SQLERRM
Deklarowanie własnego wyjątku
Wyjątek użytkownika musi zostać zadeklarowany w bloku programu, w którym ma zostać użyty, w sekcji deklaracji:
nazwa_bledu EXCEPTION;
Wywołanie wyjątku przez programistę
RAISE nazwa_bledu; - - wywołanie własnego wyjątku
RAISE TOO_MANY_ROWS; - - wywołanie wyjątku systemowego
Wyjątki zdefiniowane przez użytkownika zwracają błąd o kodzie 1 i opisie „User-Defined Exception”.
Poza tym w programie można wywołać błąd o określonym kodzie i określonym opisie:
RAISE_APPLICATION_ERROR (numer_błędu, 'tekst błędu');
Polecenie to zatrzymuje działanie podprogramu, wycofuje wszelkie zmiany dokonane przez transakcję, w ramach której podprogram jest wykonywany, ustawia zmienne SQLERRM i SQLCODE wartościami podanymi jako parametry wywołania. Numer błędu musi być z przedziału -20000 do -20999.
Przechwycenie wyjątku / błędu
Przechwycenie obsługi błędu następuje w sekcji obsługi błędów (po słownie kluczowym EXCEPTION).
EXCEPTION
WHEN wyjątek1 THEN
-- instrukcje
WHEN wyjątek2 THEN
-- instrukcje
WHEN OTHERS THEN
-- instrukcje
Możliwe jest łączenie obsługi wyjątków:
WHEN wyjątek1 OR wyjątek2 THEN
-- instrukcje
WHEN OTHERS THEN
-- instrukcje
Słowo OTHERS oznacza dowolny błąd, nie obsłużony przez wcześniejsze wyjątki. Jego obsługa nie może być łączona z innymi wyjątkami.
Wystąpienie błędu powoduje przerwanie wykonywanej instrukcji i przekazanie sterowania dla sekcji obsługi wyjątków w aktualnym bloku programu. Jeśli tam nie nastąpi jego obsługa to przekazanie nastąpi do sekcji nadrzędnej itd. Jeśli nikt nie obsłuży wyjątku to zostanie przekazany do aplikacji zewnętrznej. Ten mechanizm nazywany jest propagacją wyjątków.
BEGIN
…
BEGIN
IF X = 1 THEN
RAISE E1;
ELSIF X = 2 THEN
RAISE E2;
ELSE
RAISE E3;
END IF;
EXCEPTION
WHEN E1 THEN …
END;
…
EXCEPTION
WHEN E2 THEN …
END;
Rekordy
Rekord to struktura składająca się z wielu pól różnego typu.
W PL/SQL najczęściej rekordy wykorzystywane są do przechowywania wierszy z tabeli. Najłatwiej do tego celu użyć słowa kluczowego %ROWTYPE. Można jednak zdefiniować typ rekordowy o własnej strukturze (według własnych potrzeb).
Deklaracja typu rekordowego:
TYPE nazwa_typu_rekordowego IS RECORD
(
nazwa_pola_1 typ_pola_1,
nazwa_pola_2 typ_pola_2,
...
);
Deklaracja zmiennej rekordowej:
zmienna_rekordowa nazwa_typu_rekordowego;
Odwołanie do wartości pola rekordu:
zmienna_rekordowa.nazwa_pola_n
Przykład:
declare
type rek is record
(
d date,
k number,
o varchar2(100)
);
r rek;
begin
-- wczytanie wartości do zmiennej rekordowej
select data, kwota, opis into r from wydatki where id = 1;
-- wyświetlenie pól zmiennej rekordowej
dbms_output.put_line(r.d||' '||r.k||' '||r.o);
...
end;
Typ tablicowy
W PL/SQL dostępne są zmienne tablicowe (nie mylić z tabelami bazodanowymi). Dostępne są dwuwymiarowe, dwukolumnowe tablice. Pierwsza kolumna przechowuje identyfikator wiersza (indeks typu BINARY_INTEGER). Druga kolumna przechowuje wartość. Jeżeli istnieje konieczność wykorzystania wielu kolumn w zmiennej tablicowej, to należy zrobić tablicę, której elementami są rekordy. Tablice mogą być przekazywane jako parametry procedur i funkcji.
Deklaracja typu tablicowego:
TYPE typ_tablicowy IS
TABLE OF typ_danych [NOT NULL]
INDEX BY BINARY_INTEGER;
Deklaracja zmiennej tablicowej:
zmienna_tablicowa typ_tablicowy;
Odwołanie do zmiennej tablicowej - zwraca wartość z drugiej kolumny i-tego wiersza:
zmienna_tablicowa(i)
Zmienna tablicowa pozwala na odwoływanie się do jej atrybutów. Dostępne są następujące atrybuty:
zmienna_tablicowa.EXISTS(i) |
sprawdza czy i-ty wiersz jest określony; zwraca TRUE jeżeli jest |
zmienna_tablicowa.COUNT |
zwraca liczbę niepustych wierszy w tablicy |
zmienna_tablicowa.FIRST |
zwraca numer pierwszego niepustego wiersza |
zmienna_tablicowa.LAST |
zwraca numer ostatniego niepustego wiersza |
zmienna_tablicowa.PRIOR(i) |
zwraca numer poprzedniego niepustego wiersza względem i-tego |
zmienna_tablicowa.NEXT(i) |
zwraca numer poprzedniego niepustego wiersza względem i-tego |
zmienna_tablicowa.DELETE |
czyści zawartość tabeli |
zmienna_tablicowa.DELETE(i) |
czyści i-ty wiersz tabeli |
zmienna_tablicowa.DELETE(i,j) |
czyści wiersze od i-tego do j-tego |
Przykład
declare
type rek is record
(
d date,
k number,
o varchar2(100)
);
type tab is table of rek
index by binary_integer;
t tab;
i binary_integer := 0;
begin
for r in (select data, kwota, opis from wydatki) loop
i := i + 1;
t(i) := r;
end loop;
for i in 1 .. t.count loop
dbms_output.put_line(t(i).d||' '||t(i).k||' '||t(i).o);
end loop;
end;
Dynamiczny SQL
PL/SQL umożliwia budowania treści kolejnych poleceń do wykonania w trakcie wykonywania programu - dynamicznie.
Zwiększa to elastyczność kodu.
Poza tym umożliwia wykonywania w bloku PL/SQL wykonywania poleceń DDL i DCL.
Składnia uruchamiająca polecenie:
EXECUTE IMMEDIATE polecenie_sql
[INTO zmienna_1 [,...]
[USING [IN | OUT | IN OUT] parametr_1 [,...]]
;
polecenie_sql |
tekst zawierające polecenie SQL lub blok PL/SQL do wykonania; w tekście można używać nazw zmiennych poprzedzonych dwukropkiem; wartości tych zmiennych są określane po słowie kluczowym USING |
INTO |
można wykorzystać jeżeli uruchamiane polecenie_sql zwraca jakiś wynik; podawane są zmienne, do których ma zostać zapisany wynik uruchomionego polecenia |
USING |
podawane są wartości zmiennych wykorzystywanych w uruchamianym poleceniu_sql |
Przykłady:
DECLARE
p_sql VARCHAR2(1000);
w wydatki%ROWTYPE;
BEGIN
p_sql := 'select * from wydatki where id = :wid';
EXECUTE IMMEDIATE p_sql INTO w USING 1;
dbms_output.put_line(w.data||' '||w.kwota);
END;
DECLARE
p_sql VARCHAR2(1000);
BEGIN
p_sql := 'insert into osoby values(''X'',''ciocia Klocia'')';
EXECUTE IMMEDIATE p_sql;
p_sql := 'insert into osoby values(:z1,:z2)';
EXECUTE IMMEDIATE p_sql USING `Y', `wujek Zdzich';
END;
DECLARE
polecenie varchar2(50);
tabela varchar2(20);
warunek varchar2(50);
wynik_t varchar2(50);
nazwa_pola varchar2(20);
BEGIN
polecenie := 'select * from';
tabela := 'konta';
warunek := 'id = :z1';
nazwa_pola := 'numer';
EXECUTE IMMEDIATE
replace(polecenie,'*',nazwa_pola)||' '||tabela||' where '||warunek INTO wynik_t USING 1;
dbms_output.put_line(wynik_t);
END;
Wykorzystanie aplikacji SQL*Plus
Kompilacja obiektów
Wywołanie polecenie CREATE OR REPLACE automatycznie powoduje kompilację obiektu.
Jeżeli w wyniku kompilacji ujawnią się błędy, to obiekt ma status INVALID.
Informacje o błędnych obiektach można uzyskać poprzez zapytanie:
select * from all_objects where status = 'INVALID';
Listę błędów można listować przy pomocy polecenia:
SHOW ERRORS;
Wywołanie ponownej kompilacji wykonywane jest przez polecenia:
ALTER PROCEDURE nazwa COMPILE;
ALTER FUNCTION nazwa COMPILE;
ALTER PACKAGE nazwa COMPILE [PACKAGE];
ALTER PACKAGE nazwa COMPILE BODY;
Uruchomienie procedury / funkcji składowanej
W celu uruchomienia procedury / funkcji wykonywane jest polecenie:
EXEC nazwa_programu(parametry_wywołania);
lub
START nazwa_programu(parametry_wywołania);
Operator musi posiadać prawo EXECUTE dla obiektu.
Wyświetlanie wyników na ekran / do pliku
Aby wyniki działania programu (polecenie dmbs_output) były pokazywane na ekranie należy przed uruchomieniem programu wywołać polecenie:
SET SERVEROUTPUT ON [SIZE rozmiar]
rozmiar - określa ilość bajtów, która może zostać wyświetlona.
Aby wyniki wyświetlane na ekran były zapisywane również do pliku należy wykonać polecenie:
SPOOL ścieżna_do_pliku
wyłaczenie, przesyłania danych do pliku wywoływane jest poprzez polecenie:
SPOOL OFF
ORACLE / Programowanie w PL/SQL 2005-05-22
Łukasz Murowaniecki Strona 28 z 31