Wyklad7 2005

background image

Wyk

ład

7

background image

Język PL/SQL

Część I

background image

Rozszerzenie języka SQL o

elementy języka programowania

• SQL/PSM - Standard SQL:1999
• Oracle PL/SQL

background image

Język PL/SQL

Język

PL/SQL

jest proceduralnym

rozszerzeniem języka SQL stanowi podstawę do
pisania aplikacji Oracle – jest dostępny w
różnych programach narzędziowych ORACLE
np.

• SQL*Plus,
• Developer 2000 (Oracle*Forms i

Oracle*Reports),

• prekompilatory,
• procedury,
• wyzwalacze,
• aplikacje na stronach WWW.

background image

DECLARE

deklaracje obiektów PL/SQL jak zmienne,

stałe, wyjątki, procedury, funkcje

BEGIN

ciąg instrukcji do wykonania

EXCEPTION

obsługa wyjątków (błędów)

END

;

• Deklaracje i obsługa wyjątków są opcjonalne.

Bloki mogą być zagnieżdżone.

• Instrukcje SQL w bloku PL/SQL: SELECT,

INSERT, UPDATE, DELETE, COMMIT i
ROLLBACK.

Blok anonimowy

background image

CREATE TABLE Magazyn(Produkt

VARCHAR2(30), Stan NUMBER(4));

CREATE TABLE Zakupy(Info VARCHAR2(100),

Data DATE);

CREATE TABLE Dziennik(Rejestr

VARCHAR2(100));

INSERT INTO Magazyn VALUES('Fiat', 1);
INSERT INTO Magazyn VALUES(‘Honda', 3);
INSERT INTO Magazyn VALUES(‘Toyota', 2);

Przykładowe tabele

background image

DECLARE
v_stan NUMBER(5);

BEGIN

SELECT Stan INTO v_stan FROM
Magazyn
WHERE Produkt = 'Fiat';

IF v_stan > 0 THEN
UPDATE Magazyn SET Stan = Stan
- 1
WHERE Produkt = 'Fiat';
INSERT INTO Zakupy
VALUES ('Kupiono Fiata',
Sysdate);
ELSE
INSERT INTO Zakupy
VALUES ('Brak Fiatów',
Sysdate);
END IF;
COMMIT;
EXCEPTION
WHEN no_data_found THEN
INSERT INTO dziennik
VALUES('Nie znaleziono FIATa');
END;

Przykład

Tylko

jeden

rekord!!!

background image

• między nawiasami /* i */ , albo

• od dwóch kresek -- do końca bieżącej linii.

Komentarze

background image

v_zarobki NUMBER(7,2);

pi CONSTANT NUMBER(7,5) := 3.14159;

v_nazwisko VARCHAR2(25) := 'Kowalski';

v_data DATE := Sysdate;

żonaty BOOLEAN := False;

liczba_dzieci BINARY_INTEGER :=0;

Deklaracji zmiennych tych samych typów nie
można
łączyć razem jak w innych językach!

Deklaracje zmiennych i stałych

background image

W PL/SQL są dostępne typy danych z języka SQL a

ponadto m.in.

BOOLEAN

- wartości logiczne,

BINARY_INTEGER

- typ liczb całkowitych –

niezależny od podtypów typu NUMBER i przez to
wymagający przy zapisie mniej miejsca w pamięci
RAM.

Nie należy zmiennej nadawać tej samej nazwy co

kolumnie w tabeli.

• Wewnątrz bloku PL/SQL instrukcja SELECT nie

wypisuje wyników na ekran (ani do pliku).

• Zmienne i stałe PL/SQL mogą występować w

instrukcjach SQL.

Deklaracje zmiennych i stałych

background image

Zmienne w SQL*Plus

VARIABLE X NUMBER

(lub

CHAR(n)

lub

VARCHAR2(n)

, (n>0) – deklaracja zmiennej

wiązania;

EXECUTE :X := wyrażenie;

– przypisz na zmienną

wiązania

:X

wartość wyrażenia. Po ustaleniu

wartości można zmienne wiązania poprzedzone
dwukropkiem używać w instrukcjach SQL i PL/SQL.

PRINT X

– wypisz wartość zmiennej wiązania X;

ACCEPT Zmienna PROMPT 'Podaj wartość

zmiennej: '

– utworzenie zmiennej podstawienia i

wczytanie na nią wartości. Następnie można
zmienne podstawienia poprzedzone znakiem &
używać w instrukcjach SQL i PL/SQL.

background image

SET ServerOutput ON

ACCEPT rocz_zarob PROMPT 'Podaj roczne
zarobki: '

DECLARE

mies

NUMBER(9,2) := &rocz_zarob;

BEGIN

mies := mies/12;

DBMS_OUTPUT.PUT_LINE ('Miesięczne zarobki
= ' ||mies);

END

;

Przykład

background image

ACCEPT rocz_zarob PROMPT 'Podaj roczne
zarobki: '

VARIABLE mies NUMBER

BEGIN

:mies := &rocz_zarob/12;

END

;

/

PRINT Mies

Przykład

background image

Zmienne systemowe

SQL%ROWCOUNT

- liczba wierszy

przetworzonych przez ostatnią instrukcję SQL;

SQL%FOUND

= TRUE jeśli został znaleziony

(przetworzony) przynajmniej jeden wiersz;

SQL%NOTFOUND

= TRUE jeśli żaden wiersz nie

został znaleziony (przetworzony);

SQLERRM

- tekstowa informacja o błędzie;

SQLCODE

- kod błędu.

Obie zmienne SQLERRM i SQLCODE można

używać tylko w sekcji EXCEPTION!

background image

Przykład użycia zmiennej SQL%ROWCOUNT
do obliczenia liczby usuwanych działów o
numerze 50:

 

DECLARE

usunięte NUMBER;

BEGIN

DELETE FROM Dept WHERE Deptno
= 50;
usunięte := SQL%ROWCOUNT;
INSERT INTO DziennikDzialow
VALUES ('Dział 50', usunięte,
Sysdate);

END

;

Przykład

background image

Instrukcje warunkowe

IF

warunek

THEN

ciąg_instrukcji

END

IF

;

IF

warunek

THEN

ciąg_instrukcji

ELSE

ciąg_instrukcji

END IF

;

 

IF

warunek

THEN

ciąg_instrukcji

ELSIF

warunek

THEN

ciąg_instrukcji

END IF

• Instrukcje po THEN

są wykonywane
wtedy, gdy wartością
warunku jest TRUE.

• Instrukcje po ELSE

są wykonywane
wtedy, gdy wartością
warunku jest FALSE
lub NULL.

background image

Instrukcje iteracji

LOOP

ciąg

instrukcji

(w tym EXIT

lub EXIT WHEN warunek)

END LOOP

;

 

FOR

zmienna

IN

wartość1 ..

wartość2

LOOP

END LOOP

;

 

WHILE

warunek

LOOP

END

LOOP

;

background image

Instrukcja pusta

Null

– na przykład, gdy obsługa wyjątku

jest pusta.

background image

Zmienne wierszowe

DECLARE

rek_osoby Emp%ROWTYPE; /* Typ

wierszowy */

BEGIN

SELECT * INTO rek_osoby
FROM Emp WHERE Ename = 'KOWALSKI';
rek_osoby.Sal := 1.1*rek_osoby.Sal;
INSERT INTO Dziennik
VALUES (rek_osoby.Ename, rek_osoby.Job,
rek_osoby.Sal, SYSDATE);

END

;

Zmiennej wierszowej nie można użyć

bezpośrednio po słowie kluczowym VALUES w
instrukcji INSERT INTO!

background image

Rekordy PL/SQL, zmienne

rekordowe

TYPE

Typ_rek_prac

IS RECORD

( numer_prac NUMBER(4) NOT NULL,
nazwisko VARCHAR2(40) NOT NULL,
zarobki NUMBER(8,2),

num_działu NUMBER(4));

rekord_prac Typ_rek_prac;

Typy rekordowe mogą być zagnieżdżone. Dostęp

do pól rekordu jest przy pomocy notacji
kropkowej. Na zmienną rekordową można
przypisać wartość innej zmiennej rekordowej, ale
tylko tego samego typu rekordowego. Można ich
używać w klauzuli INTO (tak jak zmiennych
wierszowych):

SELECT * INTO rekord_prac
FROM Pracownicy
WHERE Id_prac = 12;

background image

Instrukcja SELECT w PL/SQL

Aby instrukcja była poprawna, instrukcja SELECT
… INTO
musi zwracać tylko jeden wiersz wyników!

SELECT Ename
INTO v_ename
FROM Emp
WHERE Empno = 1030;

Wartości w bloku PL/SQL, pochodzą na ogół z bazy
danych, gdzie został określony ich typ danych. W
związku z tym, wygodnie jest określać typ danych
jako ''typ danych wymienionej kolumny'' np. zamiast

DECLARE

v_ename VARCHAR2(30)

 

DECLARE

v_ename Emp.Ename%TYPE

background image

Instrukcja SELECT w PL/SQL

Możemy natomiast odebrać cały wiersz
(jeden!), a nie tylko pojedynczą kolumnę:

SELECT *
INTO v_pracownik
FROM Emp
WHERE Empno = 1030;

Zmienną v_pracownik (która jest wierszem)
deklarujemy w ten sposób:

 

DECLARE

v_pracownik Emp

%ROWTYPE

background image

Kursory: dostęp do obszarów

roboczych instrukcji SELECT

Kursor – bufor, do którego są zapisywane,

kolejno sprowadzane z bazy danych, wiersze
z wynikami zapytania.

• Definicja kursora (przyporządkowanie

instrukcji SELECT)

CURSOR nazwa_kursora IS
instrukcja_SELECT;

– (bez INTO!)

• Otwarcie kursora (wykonanie instrukcji

SELECT)

OPEN nazwa_kursora;

background image

Kursory

• Pobieranie kolejnych wierszy

FETCH nazwa_kursora INTO

zmienna, …;

• Wyjście z pętli po sprowadzeniu wszystkich

wierszy

EXIT WHEN nazwa_kursora
%NOTFOUND;

• Zamknięcie kursora

CLOSE nazwa_kursora;

background image

CREATE OR REPLACE PROCEDURE

SumujZarobki

AS

zarobki REAL:=0;

CURSOR

kursor_osoba

IS

SELECT * FROM Emp; 
rek_osoby kursor_osoba%ROWTYPE;

BEGIN

OPEN

kursor_osoba;

LOOP

FETCH

kursor_osoba INTO rek_osoby;

EXIT WHEN kursor_osoba%NOTFOUND;

zarobki := zarobki + rek_osoby.Sal;

END LOOP;

Dbms_output.Put_line('W sumie zarobki = '||
zarobki);

CLOSE

kursor_osoba;

END

;

Przykład

Nasz bufor

background image

Kursor – aliasy

kolumn

Na liście SELECT mogą się znajdować dowolne

wyrażenia, przy czym jeśli nie jest to nazwa
kolumny, musi być użyty alias np.,

 

CURSOR

kursor

IS

SELECT Ename, Sal+NVL(Comm,0) AS

Uposażenie

FROM Emp;

 Iteracja - wersja z kursorem:

FOR

rek_osoby

IN

kursor_osoba

LOOP

...

END LOOP

;

OPEN

,

FETCH

i

CLOSE

są tu

niejawne

!

background image

Kursor z

parametrami

W instrukcji SELECT w kursorze mogą

występować parametry. Ten sam kursor może
być otwarty wielokrotnie – z różnymi
wartościami parametrów.

CURSOR nazwa_kursora(parametr

typ_danych, ....) IS

instrukcja-SELECT;

DECLARE

CURSOR

emp_cursor (v_deptno NUMBER,

v_job VARCHAR2)

IS

SELECT

Empno, Ename

FROM

Emp

WHERE Deptno = v_deptno AND Job =

v_job;

BEGIN

OPEN

emp_cursor(10, 'CLERK');

...

background image

Atrybuty kursora

•   kursor%FOUND -- czy z bazy danych

sprowadzono kolejny wiersz,

kursor%NOTFOUND -- czy koniec

sprowadzania wierszy,

kursor%ROWCOUNT -- liczba

sprowadzonych dotąd wierszy,

kursor%ISOPEN -- czy kursor jest otwarty.

 

IF

NOT prac_kursor%ISOPEN

THEN

OPEN

prac_kursor;

END IF

;

LOOP

FETCH

prac_kursor...

background image

Aktualizacja wierszy za pomocą

kursora

• Przy wykonywaniu instrukcji SELECT można

zakładać blokady na wiersze w celu ich
modyfikacji.

FOR UPDATE [OF kolumna, kolumna,

… ]

Podane kolumny określają tabele, których

wiersze mają zostać zablokowane.

• Stowarzyszona z nią w instrukcji UPDATE lub

DELETE klauzula

WHERE CURRENT OF kursor

umożliwia modyfikację lub usunięcie

sprowadzonego przez kursor wiersza
odpowiedniej tabeli.

background image

DECLARE

CURSOR

kursor_osoba

IS

SELECT Ename, Sal FROM Emp

FOR UPDATE OF

Sal;

rek_osoby kursor_osoba%ROWTYPE;

BEGIN

OPEN

kursor_osoba;

LOOP

FETCH

kursor_osoba

INTO

rek_osoby;

EXIT WHEN

kursor_osoba%NOTFOUND;

IF

rek_osoby.Sal < 10000

THEN

UPDATE Emp SET Sal = Sal * 1.1

WHERE CURRENT OF

kursor_osoba;

END IF

;

/* zamiast modyfikować możemy też
usunąć wiersz np.
DELETE Emp WHERE CURRENT OF
kursor_osoba; */

END LOOP

;

CLOSE

kursor_osoba;

COMMIT;

END

;

Przykład

background image

Standardowe, nazwane wyjątki

dup_val_on_index

(ta sama wartość w

indeksie jednoznacznym),

no_data_found

(instrukcja SELECT nie

zwróciła wartości dla zmiennych w klauzuli
INTO),

too_many_rows

(instrukcja SELECT zwróciła

więcej niż jeden wiersz wartości dla
zmiennych w klauzuli INTO),

zero_divide

(dzielenie przez zero),

timeout_on_resource

(zbyt długie

oczekiwanie na zasoby),

invalid_cursor

(niepoprawna operacja na

kursorze),

invalid_number

(niepoprawna konwersja na

liczbę).

background image

Wyjątki

….. SELECT Ename, Job INTO v_ename, v_job …..
EXCEPTION

WHEN

no_data_found

THEN

INSERT INTO Dziennik VALUES ('Nikt nie zatrudniony
w 1993');
DBMS_OUTPUT.Put_line('Nikt nie zatrudniony w 93');

WHEN

too_many_rows

THEN

INSERT INTO Dziennik VALUES ('Więcej niż 1
zatrudniony w 1993');
DBMS_OUTPUT.Put_line('Więcej niż 1 w 93');

WHEN

OTHERS

THEN -- Obsługa pozostałych

błędów
komunikat := 'Błąd nr.= ' ||
SQLCODE|| ', komunikat= ' ||
Substr(SQLERRM,1,100);

-- SQLCODE i SQLERRM nie mogą wystąpić w

instrukcji SQL!

INSERT INTO Dziennik VALUES (komunikat);

DBMS_OUTPUT.Put_line(‘Wystąpił inny błąd ');

END;

background image

Obsługa wyjątków

• Jeśli blok, w którym wystąpił błąd, zawiera

obsługę tego błędu, to po dokonaniu obsługi,
sterowanie jest w zwykły sposób
przekazywane do bloku go zawierającego
(nadrzędnego).

• Jeśli nie zawiera, następuje przekazanie błędu

do bloku zawierającego dany blok i albo tam
nastąpi jego obsługa albo błąd przechodzi do
środowiska zewnętrznego.

background image

Obsługa wyjątków

• Błąd, który wystąpił w sekcji wykonawczej bloku

(między BEGIN i END) jest obsługiwany w sekcji
EXCEPTION tego samego bloku. Błędy, które
wystąpią w sekcji deklaracji lub w sekcji wyjątków
są przekazywane do bloku zawierającego dany
blok.

• Dobra praktyka programistyczna wymaga aby

każdy błąd został obsłużony – ewentualnie w
klauzuli WHEN OTHERS THEN najbardziej
zewnętrznego bloku.

• Aby móc stwierdzić, która instrukcja SQL

spowodowała błąd:

• można używać podbloków z własną obsługą
błędów, albo

• można używać licznika, zwiększającego się
o jeden po wykonaniu każdej instrukcji SQL.

background image

Wyjątki definiowane przez

programistę

Wyjątki można deklarować samemu (w sekcji
DECLARE) używając słowa kluczowego
EXCEPTION

nazwa_wyjątku EXCEPTION;

powodować ich podniesienie (w sekcji
instrukcji)

RAISE nazwa_wyjątku;

a następnie je obsługiwać (w sekcji
EXCEPTION)

WHEN nazwa_wyjątku THEN ...

background image

DECLARE

brak_w_magazynie

EXCEPTION

;

v_stan NUMBER(5);

BEGIN

SELECT Stan
INTO v_stan
FROM Magazyn WHERE Produkt =
'Fiat';

IF

v_stan < 1

THEN

RAISE brak_w_magazynie;

END IF

;

EXCEPTION

WHEN

brak_w_magazynie

THEN

INSERT INTO Zamówienia VALUES
('Fiaty');

RAISE

wyjście;

END

;

Przykład

background image

Podnoszenie wyjątku za pomocą

Raise_Application_Error

• Przypisanie mu numeru między –20000 a –20999 i

tekstu.

• Wyjątek taki może zostać obsłużony albo w tym samym

bloku albo w aplikacji zewnętrznej, w której to
wywołanie zostanie wykonane.

DECLARE
numer INTEGER;
BEGIN .....

Raise_Application_Error(-20100,'Błąd');

EXCEPTION
WHEN OTHERS THEN
numer:=SQLCODE;
IF numer= -20100 THEN
Dbms_output.Put_line('Błąd

przechwycony!');

END IF;
END;

background image

Obsługa błędów przechwytywanych

przez serwer bazy danych

Nadanie nazwy wyjątkowi systemowemu - w sekcji
deklaracji

nazwa_wyjątku EXCEPTION;

PRAGMA EXCEPTION_INIT (nazwa_wyjątku,

numer_błędu);

a następnie obsługa (w sekcji EXCEPTION)

WHEN nazwa_wyjątku THEN ...

background image

Przykład obsługi błędu naruszenia więzów klucza obcego nr
-2292:

DECLARE

bl_klucz_o

EXCEPTION

;

PRAGMA EXCEPTION_INIT

(bl_klucz_o, -2292);

v_deptno Dept.Deptno%TYPE := :b_deptno;

BEGIN

DELETE FROM Dept
WHERE Deptno = v_deptno;
COMMIT;

EXCEPTION

WHEN

bl_klucz_o

THEN

Dbms_output.Put_line ('Nie można usunąć działu '
||
To_Char(v_deptno) || ', w którym są pracownicy. ');

END

;

Przykład


Document Outline


Wyszukiwarka

Podobne podstrony:
Wyklad3 2005
Wyklad2 2005
Wyklad6 2005
Stosowana wyklad 6 2005
C Wykład V 2005 2006 s
Farmakogenetyka wyklad 2005 ze srodowiskiem i chronofarmakoterapia 2
Wyklad1 2005

więcej podobnych podstron