PL/SQL. Ćwicznia 2. Ćwiczenia 3

Podobne dokumenty
PODSTAWY BAZ DANYCH 13. PL/SQL

Bazy Danych 2007/2008 by Dzik.

DECLARE <nazwa_zmiennej> typ [(<rozmiar> )] [ NOT NULL ] [ { := DEFAULT } <wartość> ];

Materiały. Technologie baz danych. Plan wykładu Kursory. Wykład 5: Kursory jawne. Podprogramy. Kursory jawne. Kursory niejawne

Procedury składowane. Funkcje vs. procedury Funkcja. Procedura. zazwyczaj ma parametry tylko typu IN; można wywoływać z poziomu

Cheatsheet PL/SQL Andrzej Klusiewicz 1/9

1 Kursory 1. 2 Wyjątki Wyjątki predefiniowane Wyjątki niezdefiniowane wcześniej Definiowanie własnych wyjątków...

PL/SQL. Zaawansowane tematy PL/SQL

Plan wykładu Projekt fizyczny bazy danych Wprowadzenie PL/SQL PL/SQL Cechy PL/SQL

w PL/SQL bloki nazwane to: funkcje, procedury, pakiety, wyzwalacze

Język PL/SQL. Rozdział 3. Obsługa błędów wykonania Wyjątki predefiniowane i użytkownika, zgłaszanie i obsługa wyjątków.

Bazy danych wykład dwunasty PL/SQL, c.d. Konrad Zdanowski ( Uniwersytet Kardynała Stefana Bazy danych Wyszyńskiego, wykładwarszawa)

Kursory i wyjątki. (c) Instytut Informatyki Politechniki Poznańskiej 1

Październik Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska. Systemy baz danych - wykład III. dr inż.

Deklarowanie kursora

Procedury i funkcje składowane

Pakiety są logicznymi zbiorami obiektów takich jak podprogramy, typy, zmienne, kursory, wyjątki.

Bloki anonimowe w PL/SQL

Język PL/SQL Procedury i funkcje składowane

Deklarowanie kursora. CURSOR nazwa [ ( param1 typ1 [,param2 typ2]... ) ] [RETURN typ zwracany] IS zapytanie SQL;

15. Funkcje i procedury składowane PL/SQL

1. ELEMENTY JĘZYKA PL/SQL

Plan wykładu BAZY DANYCH II WYKŁAD 3. Zasięg zmiennych. Zasięg zmiennych

Oracle PL/SQL. Paweł Rajba.

DECLARE VARIABLE zmienna1 typ danych; BEGIN

Język PL/SQL. Rozdział 5. Pakiety podprogramów. Dynamiczny SQL

Język PL/SQL. Rozdział 2. Kursory

Pakiety podprogramów Dynamiczny SQL

BAZY DANYCH W APLIKACJACH SIECIOWYCH

Plan wykładu PL/SQL. PL/SQL - historia TWORZENIE APLIKACJI BAZODANOWYCH

1. Przykładowe pytania z SQL

Kursor jawny. Rozdział 10a Kursory. Deklarowanie kursora (1) Deklarowanie kursora (2)

ORACLE (Wykład 1) aragorn.pb.bialystok.pl/~aonisko. Typy rozproszonych baz danych. Systemy klient-serwer. Klient-serwer: Przykład

Oracle Developer Suite. Budowa aplikacji użytkownika końcowego

PL/SQL. Zaawansowane tematy PL/SQL. Piotr Medoń

Plan bazy: Kod zakładający bazę danych: DROP TABLE noclegi CASCADE; CREATE TABLE noclegi( id_noclegu SERIAL NOT NULL,

Kursor. Rozdział 10a Kursory. Otwieranie kursora. Deklarowanie kursora

PL/SQL. Część 1 Bloki PL/SQL. Piotr Medoń

KOLEKCJE - to typy masowe,zawierające pewną liczbę jednorodnych elementów

Tabele wykorzystywane w przykładach

BAZA DANYCH SIECI HOTELI

Obiektowe bazy danych Ćwiczenia laboratoryjne (?)

PL/SQL. Lidia Małkiewicz i Cezary Skubała

Język PL/SQL Pakiety podprogramów

Programowanie w SQL. definicja bloku instrukcji BEGIN...END, warunkowe wykonanie instrukcji IF...ELSE, wyrażenie CASE,

1 Wprowadzenie do bloków nazwanych 1. 2 Parametry 2. 3 Procedury i funkcje 3. 4 Pakiety 6. 5 Podsumowanie Źródła 10

Wyzwalacz - procedura wyzwalana, składowana fizycznie w bazie, uruchamiana automatycznie po nastąpieniu określonego w definicji zdarzenia

Technologie baz danych WYKŁAD 7: Wyjątki

Przykład 3 Zdefiniuj w bazie danych hurtownia_nazwisko przykładową funkcję użytkownika fn_rok;

Wyzwalacze. Anna Fiedorowicz Bazy danych 2

Oracle PL/SQL. Paweł Rajba.

Bloki anonimowe w PL/SQL

Programowanie w SQL procedury i funkcje. UWAGA: Proszę nie zapominać o prefiksowaniu nazw obiektów ciągiem [OLIMP\{nr indeksu}] Funkcje użytkownika

1: 2: 3: 4: 5: 6: 7: 8: 9: 10:

Hurtownia Świętego Mikołaja projekt bazy danych

Procedury wyzwalane. (c) Instytut Informatyki Politechniki Poznańskiej 1

Plan wykładu BAZY DANYCH II WYKŁAD 5. Kolekcje. Tablice asocjacyjne Kolekcje Tablice asocjacyjne VARRAY Tablice zagnieżdżone

Składowane procedury i funkcje

Zaawansowane bazy danych i hurtownie danych semestr I

Plan wykładu BAZY DANYCH II WYKŁAD 4. Co to jest kursor? Rodzaje kursorów

Wprowadzenie do języka PL/SQL. Język PL/SQL Wprowadzenie. Struktura blokowa programu. Przykładowy program w PL/SQL. Zmienne rekordowe.

Język PL/SQL Wprowadzenie

Struktura bazy danych

Funkcje w PL/SQL Funkcja to nazwany blok języka PL/SQL. Jest przechowywana w bazie i musi zwracać wynik. Z reguły, funkcji utworzonych w PL/SQL-u

Ćwiczenia laboratoryjne nr 11 Bazy danych i SQL.

Bazy danych 2 Laboratorium 2

Język PL/SQL Wprowadzenie

Wykład 5 funkcje i procedury pamiętane widoki (perspektywy) wyzwalacze

Wykład 5. SQL praca z tabelami 2

Oracle PL/SQL. Paweł Rajba.

Kolekcje Zbiory obiektów, rodzaje: tablica o zmiennym rozmiarze (ang. varray) (1) (2) (3) (4) (5) Rozszerzenie obiektowe w SZBD Oracle

OBSŁUGA WYJĄTKÓW. Mechanizm języka PL/SQL. Wyjątki:

Kursory - pobieranie danych z baz danych do programów PL/SQL

Wykład 8. SQL praca z tabelami 5

ZASTOSOWANIE PROCEDUR, FUNKCJI I PAKIETÓW

PL/SQL. Zaawansowane tematy PL/SQL

1. Wyzwalacze BD (ang. triggers)

PODSTAWY BAZ DANYCH. 17. Obiektowość w Oracle. 2009/2010 Notatki do wykładu "Podstawy baz danych"

SQL 4 Structured Query Lenguage

Zaawansowane bazy danych i hurtownie danych semestr I

Indeksy. Indeks typu B drzewo

W PostgreSQL mamy do dyspozycji nie tylko funkcje wbudowane, ale również możemy tworzyć własne. Są one zapisywane w tabeli systemowej pg_proc.

Bazy danych, 4. wiczenia

Język PL/SQL. Rozdział 6. Procedury wyzwalane

11 marca Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska. Systemy baz danych - wykład III. dr inż.

Procedury Funkcje Pakiety. Tworzenie procedury

Laboratorium nr 4. Temat: SQL część II. Polecenia DML

E.14 Bazy Danych cz. 18 SQL Funkcje, procedury składowane i wyzwalacze

Multimedialne bazy danych - laboratorium

2 PL/SQL - podstawy Zmienne i stałe Operatory SQL w PL/SQL Instrukcje sterujące... 8

CREATE TABLE autorzy ( id_autora SERIAL PRIMARY KEY, imie TEXT, nazwisko TEXT );

Struktury sterowania PL/SQL

Systemy baz danych 2 laboratorium Projekt zaliczeniowy

Podprogramy. Rozdział 11 Procedury i funkcje składowane

Wykład 9. Pakiety w języku PL/SQL

strukturalny język zapytań używany do tworzenia i modyfikowania baz danych oraz do umieszczania i pobierania danych z baz danych

Język PL/SQL. Rozdział 4. Procedury i funkcje składowane

Wyzwalacze. do automatycznego generowania wartości kluczy głównych. Składnia instrukcji tworzacej wyzwalacz

Plan wykładu BAZY DANYCH II WYKŁAD 2. Bloki. Struktura bloku

SQL (ang. Structured Query Language)

Transkrypt:

PL/SQL Ćwicznia 2 4. Napisać kod bloku animowanego w PL/SQL, za pomocą którego z tabeli osoby będzie można wybrać osobę o określonym nazwisku i imieniu, przy czym nazwisko i imię tej osoby jest podane poprzez zainicjowanie dwóch odpowiednich zmiennych PL/SQL. Należy wyświetlić pozostałe dane tej osoby. Poszukujemy nazwisko i imię Lis Jan. o_imie1 VARCHAR(20):='Jan'; o_nazwisko VARCHAR(20):='Lis'; SELECT imie1,nazwisko INTO o_imie1, o_nazwisko FROM osoby WHERE imie1=o_imie1, INITCAP(nazwisko)=o_Nazwisko; DBMS_OUTPUT.PUT_LINE(o_Imie ' ' o_nazwisko); 4a) Napisać kod bloku animowanego w PL/SQL, za pomocą którego z tabeli osoby będzie można wybrać osobę o określonym nazwisku i imieniu, przy czym nazwisko i imię tej osoby jest podane poprzez zainicjowanie jednej zmiennej PL/SQL wartością Lis Jan. Należy wyświetlić pozostałe dane tej osoby. o_dane VARCHAR(20):='Jan Lis'; SELECT imie1 ' ' nazwisko dane INTO o_dane FROM osoby WHERE imie1 ' ' INITCAP(nazwisko)=o_dane; DBMS_OUTPUT.PUT_LINE(o_dane); Ćwiczenia 3 1'. Napisać kod bloku animowanego języka PL/SQL za pomocą którego będzie można wyświetlić tę osobę( nazwisko, imię, pensja) które jest aktualnie zatrudniona i aktualnie pobiera maksymalną pensje, przy czym płeć tej osoby jest zainicjowana przez odpowiednią zmienną. o_plec CHAR(1):='K'; o_nazwisko VARCHAR(20); o_imie1 VARCHAR(20); p_pensja NUMBER(2); SELECT o.nazwisko, o.imie1, p.pensja INTO o_nazwisko, o_imie1, p_pensja FROM osoby o, pensje p,zatrudnienia z 1

WHERE o.plec=o_plec and o.id=z.id_os and o.id=p.id_os and z.do is null and p.do is null and p.pensja=(select MAX(p.pensja) FROM osoby o,zatrudnienia z, pensje p WHERE o.plec=o_plec and o.id=z.id_os and o.id=p.id_os and z.do is null and p.do is null); DBMS_OUTPUT.PUT_LINE(o_Nazwisko ' ' o_imie1 ' ' p_pensja); 2`. Napisać kod bloku animowanego w PL/SQL za pomocą którego zostanie wyświetlony komunikat: osoba wybrana, która jest imie i nazwisko ma inicjały Przy czym należy wykorzystać 2 zmienne PL/SQL do podstawienia inicjałów, których typ jest zainicjowany jako podtyp typu tekstowego o stałej długości 1. Osoba jest dana poprzez indetyfikator (id) zainicjowanie zmiennej PL/SQL. o_id NUMBER:=1; SUBTYPE inicjal IS CHAR(1); o_inic1 inicjal; o_inic2 inicjal; o_nazwisko VARCHAR(20); o_imie1 VARCHAR(20); SELECT INITCAP(nazwisko), imie1,initcap(substr(nazwisko,1,1)), SUBSTR(imie1,1,1) INTO o_nazwisko, o_imie1,o_inic1,o_inic2 FROM osoby WHERE id=o_id; DBMS_OUTPUT.PUT_LINE('Osoba wybrana,ktora jest ' o_nazwisko ' ' o_imie1 ' ma inicjaly ' o_inic1 ' ' o_inic2); 1. Napisać kod bloku animowanego w PL/SQL za pomocą którego zostaną wyświetlone dane tej osoby, która kiedykolwiek była zatrudniona przez najdłuższy okres czasu na wydziale, którego nazwa jest podana poprzez zainicjowanie odpowiedniej zmiennej. o_nazwisko VARCHAR(20); o_imie VARCHAR(20); w_nazwa VARCHAR(10):='prawo'; SELECT o.nazwisko, o.imie INTO o_nazwisko, o_imie1 From osoby o,zatrudnienia z,wydzialy w WHERE o.id=z.id_os and w.nazwa=w_nazwa and z.id_wydz=w.id and (sysdate-z.od)= (Select MAX(sysdate-z1.od) from osoby o1,zatrudnienia z1, wydzialy w1 where o1.id=z1.id_os and w1.nazwa=w_nazwa and z1.id_wydz=w1.id); DBMS_OUTPUT.PUT_LINE(o_Nazwisko ' ' o_imie1); 2. Napisać kod bloku animowanego w PL/SQL za pomocą którego będzie można wyświetlić nazwę tego wydziału, na którym liczba wszystkich kiedykolwiek 2

zatrudnionych osób była największa, przy czym płeć tych osób jest podana poprzez zainicjowanie odpowiedniej zmiennej. PL CHAR(1):='M'; WYNIK VARCHAR(30); SELECT NAZWA INTO WYNIK FROM WYDZIALY WHERE ID = (SELECT ID FROM (SELECT COUNT (Z.ID_WYDZ) ILE,Z.ID_WYDZ ID FROM ZATRUDNIENIA Z, OSOBY O WHERE O.ID=Z.ID_OS AND O.PLEC=PL GROUP BY Z.ID_WYDZ) WHERE ILE =( SELECT MAX(ILE) FROM( SELECT COUNT (Z.ID_WYDZ) ILE,Z.ID_WYDZ FROM ZATRUDNIENIA Z, OSOBY O WHERE O.ID=Z.ID_OS AND O.PLEC=PL GROUP BY Z.ID_WYDZ))); DBMS_OUTPUT.PUT_LINE( '' WYNIK ''); Ćwiczenia 4 (Typy rekordowe) 1a) Zdefiniować typ rekordowy t_rekordosoba i przy jego wykorzystaniu wyświetlić dane osoby o id poprzez zdefiniowanie odpowiedniej zmiennej PL/SQL. TYPE t_recordosoba IS RECORD ( o_id osoby.id%type, o_nazwisko osoby.nazwisko%type, o_imie1 osoby.imie1%type, o_imie2 osoby.imie2%type, o_plec osoby.plec%type, o_d osoby.d_ur%type ); osoba t_recordosoba; o_id1 NUMBER:=1; SELECT o.id, o.nazwisko,o.imie1,o.imie2, o.plec,o.d_ur INTO osoba FROM osoby o 3

WHERE o.id=o_id1; DBMS_OUTPUT.PUT_LINE('Osoba o id=' osoba.o_id 'to' osoba.o_imie1 ' ' osoba.o_nazwisko ' dacie urodzenia ' osoba.o_d); b) wykorzystanie rekordu niejawnego osoba osoby%rowtype; o_id1 NUMBER:=1; SELECT o.id, o.nazwisko,o.imie1,o.imie2, o.d_ur,o.plec INTO osoba FROM osoby o WHERE o.id=o_id1; DBMS_OUTPUT.PUT_LINE('Osoba o id=' osoba.id 'to' osoba.imie1 ' ' osoba.nazwisko ' dacie urodzenia ' osoba.d_ur); 2. Zdefiniować 2 type rekordowe użytkownika t_rekordosoba1 I t_recordosoba2 zawierające następujące pola: z_id, z_nazwisko, z_imie, z_data_ur. Następnie zadeklarować po 2 zmienne dla każdego z tych typów recordowych. Niech pola jednej z tych zmiennych z_id=20, z_nazwisko=kowalska, z_imie=maria, z_data_ur=23/05/1981. Dokonać próby przypisania tych wartości pozostałym zadeklarowanych zmiennych rekordowych. TYPE t_recordosoba1 IS RECORD ( z_id osoby.id%type, z_nazwisko osoby.nazwisko%type, z_imie osoby.imie1%type, z_data_ur osoby.d_ur%type ); TYPE t_recordosoba2 IS RECORD ( z_id osoby.id%type, z_nazwisko osoby.nazwisko%type, z_imie osoby.imie1%type, z_data_ur osoby.d_ur%type ); os1 t_recordosoba1; os2 t_recordosoba2; 4

os1.z_id:=20; os1.z_nazwisko:='kowalska'; os1.z_imie:='maria'; os1.z_data_ur:=to_date('23/05/1981','dd/mm/yyyy'); os2.z_id:=os1.z_id; os2.z_nazwisko:=os1.z_nazwisko; os2.z_imie:=os1.z_imie; os2.z_data_ur:=os1.z_data_ur; 3.a) Wstawić do tabeli wiersz danych id=15, nazwisko=pawlowska,imie1=marta, data_ur=06/07/1982, plec=k. Wstawienie wiersza danych do tabeli bazodanowej przeprowadzić z wykorzystaniem zmiennej rekordowej. osoba osoby%rowtype; osoba.id:=15; osoba.nazwisko:='pawlowska'; osoba.imie1:='marta'; osoba.data_ur:=to_date('06/07/1982', 'DD/MM/YYYY'); osoba.plec:='k'; INSERT INTO osoby VALUES osoba; COMMIT; b) W punkcie a) zostały podane błędne dane ustawionego rekordu. Poprawne dane są następujące id=15, nazwisko=pawłowki imie=marek data_ur=05/05/1980, plec=m. Dokonaj korekty błędu ustawionego wiersza danych z wykorzystaniem zmiennej rekordowej. osoba osoby%rowtype; osoba.id:=15; osoba.nazwisko:='pawlowski'; osoba.imie1:='marek'; osoba.data_ur:=to_date('05/05/1980', 'DD/MM/YYYY'); osoba.plec:='m'; UPDATE osoby SET ROW=osoba WHERE id=15; COMMIT; c) Niektóre z poprawionych danych w punkcie b) nadal są błędne osoba o id=15 ma nazwisko Pawelski I data_ur=20/07/1982 pozostałe dane są poprawne. Dokonaj korekty błędnych danych wykorzystując w tym celu zmienną rekordową. 5

OS OSOBY%ROWTYPE; select id, imie1,imie2,d_ur,plec into os.id,os.imie1,os.imie2,os.d_ur,os.plec from osoby where id=15; os.nazwisko:='pawelski'; update OSOBY set row=os where id=15; Ćwiczenia 5 (if, for, while, loop) 1. Napisać kod bloku anonimowego PL/SQL, za pomocą którego dla dowolnej osoby danej za pomocą id podanego w odpowiedniej zmiennej PL/SQL -owej zostanie wyświetlony komunikat dotyczącej sumy jej nazwiska i mienia. I tak gdy długość jest mniejsza od 9 "osoba o krótkiej długości imienia i nazwiska", gdy od 10 do 20 " osoba o długiej nazwiska i imienia", zaś ponad 20 - "osoba o bardzo długiej długości imienia i nazwiska" o_id osoby.id%type:=1; opis VARCHAR2(60); o_dl NUMBER(2); SELECT length(o.nazwisko)+length(o.imie1) INTO o_dl FROM osoby o WHERE o.id=o_id; IF o_dl < 9 THEN opis:='osoba o krotkiej dlugosci imienia i nazwiska'; ELSIF o_dl > 10 AND o_dl < 20 THEN opis:='osoba o dlugiej dlugosci imienia i nazwiska'; ELSE opis:='osoba o bardzo dlugiej dlugosci imienia i nazwiska'; END IF; DBMS_OUTPUT.PUT_LINE(opis); 2. Napisać kod bloku anonimowego PL/SQL, za pomocą którego dla dowolnej osoby za pomocą id podanego w odpowiednio w odpowiednio zainicjowanej zmiennej PL/SQL - owej zostanie wyświetlony komunikat dotyczący daty jej urodzin. Osoba o id = 1. Tj. Lis Jan urodził się w 4 kwartale. Nie wolno stosować interwału czasowego określającego kwartał. o_id osoby.id%type:=1; opis VARChAR2(60); o_miesiac NUMBER; SELECT TO_NUMBER(TO_CHAR(d_ur,'MM')) INTO o_miesiac 6

FROM osoby WHERE id=o_id; IF o_miesiac < 4 THEN opis:='osoba o id= ' o_id ' urodzila sie w 1 kwartale'; ELSIF o_miesiac <7 THEN opis:='osoba o id= ' o_id ' urodzila sie w 2 kwartale'; ELSIF o_miesiac < 10 THEN opis:='osoba o id= ' o_id ' urodzila sie w 3 kwartale'; ELSE opis:='osoba o id= ' o_id ' urodzila sie w 4 kwartale'; END IF; DBMS_OUTPUT.PUT_LINE(opis); 3. Napisać kod blok anonimowego PL/SQL, za pomocą którego dla aktualnej osoby podaje za pomocą id podanego w odpowiednio zainicjowanej zmiennej PL/SQL - owej zostanie wyświetlony komunikat dotyczący aktualnie pobranej pensji - do której grupy wynagrodzeń należy pensja. Poniżej 800zl - grupa I, od 801 do 1100 - grupa II, od 1101 do 1400zl - grupa III itd. co 300 zł. Zaś po 2000zl co 500zl nowa grupa, zaś po 6000 zł - grupa XIII. Osoba o id = 3 tj. Norek Tadeusz pobiera aktualnie pensje w wysokości 1800zl - V grupa wynagrodzeń. Zastosować instrukcje CASE wyszukująca. o_id osoby.id%type:=3; p_pensja pensje.pensja%type; opis VARCHAR2(60); SELECT p.pensja INTO p_pensja FROM osoby o, pensje p WHERE o.id=o_id AND p.id_os=o_id AND p.do IS NULL; CASE WHEN p_pensja < 800 THEN opis:='osoba o id=' o_id 'pobiera pensje ' p_pensja ' - grupa I'; WHEN p_pensja > 801 AND p_pensja < 1100 THEN opis:='osoba o id=' o_id 'pobiera pensje ' p_pensja ' - grupa II'; WHEN p_pensja > 1100 and p_pensja < 1400 THEN opis:='osoba o id=' o_id 'pobiera pensje ' p_pensja ' - grupa III'; WHEN p_pensja > 1401 and p_pensja < 1700 THEN opis:='osoba o id=' o_id 'pobiera pensje ' p_pensja ' - grupa IV'; WHEN p_pensja >1701 and p_pensja < 2000 THEN opis:='osoba o id=' o_id 'pobiera pensje ' p_pensja ' - grupa V'; WHEN p_pensja > 2001 and p_pensja < 3000 THEN opis:='osoba o id=' o_id 'pobiera pensje ' p_pensja ' - grupa VI'; WHEN p_pensja > 3001 and p_pensja < 4000 THEN opis:='osoba o id=' o_id 'pobiera pensje ' p_pensja ' - grupa VII'; WHEN p_pensja > 4001 and p_pensja < 5000 THEN opis:='osoba o id=' o_id 'pobiera pensje ' p_pensja ' - grupa VIII'; WHEN p_pensja > 5001 and p_pensja < 6000 THEN opis:='osoba o id=' o_id 'pobiera pensje ' p_pensja ' - grupa IX'; 7

ELSE opis:='nie ma aktualnej pensji '; END CASE; DBMS_OUTPUT.PUT_LINE(opis); 4. Napisać kod bloku anonimowego PL/SQL, za pomocą którego dla dowolnej osoby zadanej przez jej id w odpowiednio zainicjowanej PL/SQL - owej zostanie wyświetlony odpowiedni komunikat dotyczący daty urodzenia. Osoba o id = 1 tj. Lis Jan urodził się w październiku. Zastosować instrukcje CASE sprawdzająca. zm_id osoby.id%type:=2; zm_dane VARCHAR(40); zm_mies NUMBER(2); zm_miesiac VARCHAR(15); SELECT imie1 ' ' nazwisko, TO_NUMBER(TO_CHAR(d_ur,'mm')) INTO zm_dane, zm_mies FROM osoby WHERE id=zm_id; CASE zm_mies WHEN 1 THEN zm_miesiac:='styczeniu'; WHEN 2 THEN zm_miesiac:='lutym'; WHEN 3 THEN zm_miesiac:='marcu'; WHEN 4 THEN zm_miesiac:='kwietniu'; WHEN 5 THEN zm_miesiac:='maju'; WHEN 6 THEN zm_miesiac:='czerwcu'; WHEN 7 THEN zm_miesiac:='lipiecu'; WHEN 8 THEN zm_miesiac:='sierpniu'; WHEN 9 THEN zm_miesiac:='wrzesniu'; WHEN 10 THEN zm_miesiac:='pazdzierniku'; WHEN 11 THEN zm_miesiac:='listopadzie'; WHEN 12 THEN zm_miesiac:='grudniu'; END CASE; DBMS_output.put_line('osoba o id= ' zm_id 'tj. ' zm_dane ' urodzila sie w ' zm_miesiac ''); 5. Napisać kod bloku anonimowego PL/SQL, za pomocą którego dla pierwszych 10 osób zostanie wyświetlony komunikat 1. Lis Jan ma inicjały L.J. 2. Kot Adam ma inicjały K.A.... 10. Murek Danuta ma inicjały M.D. a) zastosować pętle prosta b) zastosować pętle WHILE licznik NUMBER:=1; 8

o_in1 CHAR(1); o_in2 CHAR(1); o_imie osoby.imie%type; o_naz osoby.nazwisko%type; LOOP SELECT nazwisko, imie1, SUBSTR(nazwisko,1,1), SUBSTR(imie1,1,1) INTO o_imie, o_naz, o_in1, o_in2 FROM osoby WHERE id=licznik; EXIT WHEN licznik=10; END LOOP; Ćwiczenia 6 (Instrukcje SQL) 1. Napisać kod bloku anonimowego PL/SQL, który umożliwia zwrot identyfikatora wiersza danych zmodyfikowanego instrukcja DML. W tym celu do tabeli osoby wprowadzić przykładowy wiersz danych id=12, nazwisko='tomczyk', imie='monika', d_ur='21/01/1987',plec='k' i wydrukować identyfikator wprowadzonego wiersza danych. Następnie dla wiersza danych tabeli osoby, którego identyfikator jest równy identyfikatorem wprowadzonego wiersza danych dodać operacje aktualizacji d_ur='12/01/1987' pobrać nazwisko, imię, i datę urodzenia osoby aktualizowanej a następnie je wydrukować. W końcu dokonać operacji usunięcia wiersza danych z tabeli osoby którego identyfikator jest równy identyfikatorowi wprowadzonego wiersza. Pobrać ten identyfikator i wydrukować go. o_rowid ROWID; o_id osoby.id%type; o_imie osoby.imie1%type; o_nazwisko osoby.nazwisko%type; o_data osoby.d_ur%type; o_plec osoby.plec%type; INSERT INTO osoby(id, nazwisko,imie1,imie2, d_ur, plec) VALUES (12,'Tomczyk','Monika', NULL, TO_DATE('21/01/1987','dd/mm/yyyy'), 'K') RETURNING rowid INTO o_rowid; DBMS_OUTPUT.PUT_LINE('indentyfikator wstawionego wiersza' o_rowid ' '); UPDATE osoby SET d_ur=to_date('12/01/1987', 'dd/mm/yyyy') WHERE rowid=o_rowid RETURNING nazwisko, imie1, d_ur INTO o_nazwisko, o_imie, o_data; DBMS_OUTPUT.PUT_LINE( ' ' o_nazwisko ' ' o_imie ' ' o_data ' '); DELETE FROM osoby WHERE rowid=o_rowid RETURNING rowid INTO o_rowid; DBMS_OUTPUT.PUT_LINE( 'indentyfikator usunietego wiersza to ' o_rowid ' '); 9

2. Napisać kod bloku anonimowego PL/SQL wykorzystującego pętle numeryczna w celu wyświetlenia z listy osób aktualnie zatrudnionych na każdym wydziale (liczba wydziałów i osób jest dowolna) Lista osób aktualnie zatrudniona na wydziale Fizyka 1. Norek Tadeusz 2. Kula Katarzyna 3. Murek Danuta Lista osób aktualnie zatrudniona na wydziale Matematyka 1. Kot Adam 2. Lis Anna 3.... z_licznik1 BINARY_INTEGER:=1; z_licznik2 BINARY_INTEGER:=1; z_ile1 NUMBER(2); z_ile2 NUMBER(2); w_nazwa wydzialy.nazwa%type; o_nazwisko osoby.nazwisko%type; o_imie osoby.imie1%type; SELECT COUNT(id) INTO z_ile1 FROM wydzialy; FOR z_licznik1 IN 1..z_ile1 LOOP SELECT nazwa INTO w_nazwa FROM wydzialy WHERE id=z_licznik1; DBMS_OUTPUT.PUT_LINE('Lista osob aktualnie zatrudnionych na wydziale ' w_nazwa ''); SELECT COUNT(*) INTO z_ile2 FROM zatrudnienia; WHERE id_wydz=z_licznik AND do IS null; FOR z_licznik2 IN 1..z_ile2 SELECT o.imie1, o.nazwisko INTO o_imie, o_nazwisko FROM osoby o, zatrudnienia z WHERE o.id=z.id_os AND z.id_wydz=z_licznik And z.do is null; DBMS_OUTPUT.PUT_LINE('' z_licznik2 ' ' o_nazwisko '' o_imie ' '); END LOOP; END LOOP; 3. Napisać kod bloku anonimowego PL/SQL wykorzystującego pętle numeryczna w celu wyświetlenia listy osób aktualnie zatrudnionych w poszczególnych rokach i miesiącach (poczynając od aktualnego roku a kończąc na najstarszym 10

Ćwiczenia 7 (kursory) 1a) Napisać kod bloku anonimowego PL/SQL z wykorzystaniem kursora jawnego, którego dla dowolnej osoby z tabeli osoby będzie wyświetlał komunikat: "Osoba nazwisko i imię ma inicjały" Wykorzystac: * petla prosta * petle while zm_imie1 osoby.imie1%type; zm_nazwisko osoby.nazwisko%type; zm_in1 CHAR(1); zm_in2 CHAR(1); CURSOR k_osoby IS SELECT imie1, INITCAP(nazwisko), SUBSTR(imie1,1,1), SUBSTR(nazwisko,1,1) FROM osoby; OPEN k_osoby; LOOP FETCH k_osoby INTO zm_imie1, zm_nazwisko, zm_in1,zm_in2; EXIT WHEN k_osoby%notfound; DBMS_OUTPUT.PUT_LINE('Osoba ' zm_imie1 ' ' zm_nazwisko ' ma inicjaly ' zm_in1 '.' zm_in2 '. '); END LOOP; CLOSE k_osoby; 1b) zm_imie1 osoby.imie1%type; zm_nazwisko osoby.nazwisko%type; zm_in1 CHAR(1); zm_in2 CHAR(1); CURSOR k_osoby IS 11

SELECT imie1, INITCAP(nazwisko), SUBSTR(imie1,1,1), SUBSTR(nazwisko,1,1) FROM osoby; zm_dane k_osoby%rowtype; OPEN k_osoby; FETCH k_osoby INTO zm_imie1, zm_nazwisko, zm_in1,zm_in2; WHILE k_osoby%found LOOP DBMS_OUTPUT.PUT_LINE('Osoba ' zm_imie1 ' ' zm_nazwisko ' ma inicjaly ' zm_in1 '.' zm_in2 '. '); FETCH k_osoby INTO zm_imie1, zm_nazwisko, zm_in1,zm_in2; END LOOP; CLOSE k_osoby; 2 Napisać kod bloku anonimowego PL/SQL z kursorem jawnym (z blokada), którego zadaniem jest podniesienie o 50zl aktualnej pensji osoba aktualnie zatrudnionym, które jeszcze nie miały podwyżki. Transakcje zatwierdzić. z_id osoby.id%type; CURSOR k_aktualizacja IS SELECT o.id FROM pensje p, zatrudnienia z, osoby o WHERE o.id = z.id_os AND o.id = p.id_os AND z.do IS NULL AND o.id IN ( SELECT id_os FROM pensje GROUP BY id_os HAVING COUNT(*) <= 1 ) FOR UPDATE OF p.pensja; OPEN k_aktualizacja; FETCH k_aktualizacja INTO z_id; WHILE k_aktualizacja%found LOOP DBMS_OUTPUT.PUT_LINE(z_id); UPDATE pensje SET pensja = pensja + 50 WHERE id_os = z_id; FETCH k_aktualizacja INTO z_id; END LOOP; COMMIT; 3 Mamy dokonać podwyżki pensji aktualnej pensji osobom aktualnie zatrudnionym. Każda z tych osób ma dostać taka kwotę podwyżki, jaka wynika z okresu jej pracy na danym wydziale za każdy przepracowany rok osoba dostaje podwyżkę w wysokości 3% kwoty swojej aktualnej pensji. Transakcje zatwierdzić. zm_id pensje.id_os%type; zm_pensja pensje.pensja%type; CURSOR k_pensja IS 12

SELECT z.id_os,trunc((months_between(sysdate,p.od)/12)*0.03*p.pensja+p.pensja) koncowa FROM pensje p,zatrudnienia z WHERE p.id_os=z.id_os AND p.do IS NULL AND z.do IS NULL; OPEN k_pensja; LOOP FETCH k_pensja INTO zm_id, zm_pensja; EXIT WHEN k_pensja%notfound; UPDATE pensje SET pensja=zm_pensja WHERE id_os=zm_id; END LOOP; CLOSE k_pensja; COMMIT; Ćwiczenia 8 (obsługa wyjątków) 1. Zaprojektować blok w którym w jego części wykonawczej zmiennej z_nazwisko typu VARCHAR(10) przypisano wartość 'Nowak-Konopacka'. Zaprojektować obsługę tego błędu za pomocą wyjątku predefiniowanego, przy czym obsługa błędu polega na wyświetleniu komunikatu:"zbyt długi ciąg znaków alfanumerycznych" z_nazwisko VARCHAR2(10); z_nazwisko:='nowak-konopacka'; EXCEPTION WHEN VALUE_ERROR THEN DBMS_OUTPUT.PUT_LINE ('Zbyt dlugi ciag znakow alfanumerycznych'); 2. Zaprojektować blok PL/SQL z kursorem niejawnym którego zadaniem jest wyświetlanie osób aktualnie zatrudnionych i liczbę pełnych przepracowanych lat w danym miejscu zatrudnienia, przy czym należy wyświetlić te osoby których liczba lat jest większa (mniejsza) niż liczba podawana w pewnej zmiennej. Zaprojektować obsługę wyjątków poprzez wyjątki predefiniowane które wyłapią wszystkie możliwe błędy i wyświetla odpowiednie komentarze. Dodatkowo zaprojektować poprzez wyjątek predefiniowany obsługę dowolnego błędu. z_liczba NUMBER:=10; z_imie osoby.imie1%type; z_nazwisko osoby.nazwisko%type; z_lata NUMBER; SELECT o.imie1, o.nazwisko,trunc((months_between(sysdate, z.od))/12) 13

INTO z_imie,z_nazwisko,z_lata FROM zatrudnienia z, osoby o WHERE o.id=z.id_os AND z.do IS NULL AND TRUNC((MONTHS_BETWEEN(SYSDATE, z.od))/12) > z_liczba; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('nie znaleziono danych'); WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE('za duzo danych'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('inny blad'); 3. Do bazy danych został a wprowadzona osoba o id=11, której dane zostały wprowadzone blednie. Należy zaprojektować obsługę wyjątków, która wyłapie wszystkie te błędy i wyświetli komentarze: a)data urodzenia jest późniejsza niż data zatrudnienia! b)data zatrudnienia jest późniejsza niż data zwolnienia! c)data urodzenia jest późniejsza niż data zatrudnienia i data zatrudnienia jest późniejsza niż data zwolnienia! z_id osoby.id%type:=11; z_data_zat zatrudnienia.od%type:='23/11/1999'; z_data_zwol zatrudnienia.do%type:='21/02/1989'; z_data_ur osoby.d_ur%type:='12/06/1970'; wyjatek1 EXCEPTION; wyjatek2 EXCEPTION; wyjatek3 EXCEPTION; INSERT INTO osoby(id, nazwisko,imie1,imie2, d_ur, plec) VALUES (11,'Nowak','Monika', NULL, TO_DATE('z_data_ur','DD/MM/YYYY'),'K'); INSERT INTo zatrudnienia(id,id_os, od,do,id_wydz) VALUES (11,11,TO_DATE('z_data_zat','DD/MM/YYYY'),TO_DATE('z_data_zwol','DD/MM/YYYY' ),2); IF z_data_ur > z_data_zat THEN RAISE wyjatek1; ELSIF z_data_zat > z_data_zwol THEN RAISE wyjatek2; ELSIF z_data_ur > z_data_zat AND z_data_zat > z_data_zwol THEN RAISE wyjatek3; END IF; EXCEPTION WHEN wyjatek1 THEN DBMS_OUTPUT.PUT_LINE('data urodzenia jest pozniejsza niz data zatrudnienia'); WHEN wyjatek2 THEN 14

DBMS_OUTPUT.PUT_LINE('data zatrudnienia jest pozniejsza niz data zwolnienia '); WHEN wyjatek3 THEN DBMS_OUTPUT.PUT_LINE('data urodzenia jest pozniejsza niz data zatrudnienia i data zatrudnienia jest pozniejsza niz data zwolnienia '); 4. Zaprojektować blok PL/SQL-owy z kursorem niejawnym którego zadaniem jest wyświetlenie id osoby i jej inicjałów osób, które mają drugie imię. Zaprojektować obsługę wyjątków. Za pomocą wyjątku predefiniowanego, który obsługuje dowolny błąd. Obsługa polega na wpisaniu do tabeli tabela_bledow kodu wykrytego błędu i przypisanego mu komentarza (max. 200 znaków długości). osoba osoby%rowtype; in1 CHAR(1); in2 CHAR(1); komentarz VARCHAR(200); SELECT id, nazwisko, imie1, imie2, d_ur, plec, SUBSTR(nazwisko,1,1), SUBSTR(imie1,1,1) INTO osoba, in1,in2 FROM osoby WHERE imie2 IS NOT NULL; DBMS_OUTPUT.PUT_LINE('dane osoby: ' id.osoba ' ' imie1.osoba ' ' imie2.osoba ' ' nazwisko.osoba ' ' d_ur.osoba ' ' plec.osoba ' inicjaly: ' in1 ' ' in2); EXCEPTION WHEN NO_DATA_FOUND THEN komentarz:='nie znaleziono danych'; INSERT INTO tab_bledow VALUES(-1403,komentarz); WHEN TOO_MANY_ROWS THEN komentarz:='za duzo danych'; INSERT INTO tab_bledow VALUES(-1422,komentarz); WHEN OTHERS THEN komentarz:='inny blad'; INSERT INTO tab_bledow VALUES(0,komentarz); 5. W zadaniu z pętlami numerycznymi FOR, które umożliwiały w poszczególnych latach i ich miesiącach wyświetlenie liczby, zatrudnionych osób tak zaprojektować obsługę wyjątków, aby wyświetliły również te lata i ich miesiące, w których nikogo nie zatrudniono (tj. z lista zatrudnionych osób) 15

Ćwiczenia 9 (podprogramy: procedury, funkcje) 1. Zaprojektować procedurę, które umożliwi wprowadzanie danych osoby do tabeli osoby. Należy przy tym zaprojektować obsługę błędów wprowadzono do tabeli osoby danych osoby już wprowadzonej. CREATE OR REPLACE PROCEDURE nowa (i_id IN osoby.id%type, i_nazwisko IN osoby.nazwisko%type, i_imie1 IN osoby.imie1%type, i_imie2 IN osoby.imie2%type, i_d_ur IN osoby.d_ur%type, i_plec IN osoby.plec%type) AS INSERT INTO osoby(id, nazwisko, imie1, imie2, d_ur, plec) VALUES(i_id, i_nazwisko, i_imie1, i_imie2, i_d_ur, i_plec); EXCEPTION END nowa; DBMS_OUTPUT.PUT_LINE('Dane zostaly wprowadzone!'); WHEN DUP_VAL_ON_INDEX THEN DBMS_OUTPUT.PUT_LINE('Taka osoba juz istnieje!'); EXECUTE nowa (20, 'Kowalski', 'Jan', 'Janek', TO_DATE('13/10/1985','dd/mm/yyyy'), 'm'); 2.Zaprojektowac procedurę i funkcje w języku PL/SQL, która umożliwia obliczenie osób danej płci w tabeli osoby. Następnie wywołać podprogramy PL/SQL. W środowisku SQL i wynik wydrukować. CREATE OR REPLACE PROCEDURE liczosoby( z_plec osoby.plec%type) AS liczba NUMBER; SELECT count(id) ilosc INTO liczba FROM osoby WHERE plec=z_plec; --RAISE APPLICATION_ERROR(liczba,'Liczba osob'); END liczosoby; liczosoby('k'); CREATE OR REPLACE FUNCTION liczbaosob ( z_plec osoby.plec%type ) 16

RETURN NUMBER IS liczba NUMBER; SELECT count(id) ilosc INTO liczba FROM osoby WHERE plec=z_plec; RETURN liczba; END liczbaosob; z_plec osoby.plec%type:='m'; liczba NUMBER; liczba:=liczbaosob(z_plec); DBMS_OUTPUT.PUT_LINE('Liczba osob o danej plci ' z_plec ' wynosi ' liczba); 3. Zaprojektować funkcje PL/SQL, która dla danego wydziału poda informacje o procencie osób aktualnie zatrudnionych osób na nim w stosunku do liczby wszystkich osób aktualnie zatrudnionych w następujący sposób: "Wydział zatrudnia ponad 50% ogółu zatrudnionych" lub "Wydział zatrudnia ponad 25% ogółu zatrudnionych" lub "Wydział zatrudnia poniżej 25% ogółu zatrudnionych" lub "Na wydziale nikt nie jest zatrudniony" zastosować konstrukcje bloku funkcyjnego z więcej niż jedna instrukcja RETURN. Drukowanie wyniku działania funkcji w bloku. Wyniki wydrukować dla wszystkich wydziałów. CREATE OR REPLACE FUNCTION l_zatrudnionych (z_wydzial wydzialy.nazwa%type) RETURN VARCHAR2 IS l_wydz NUMBER; l_wszyscy NUMBER; SELECT count(o.id) ilosc INTO l_wszyscy FROM osoby o, zatrudnienia z WHERE o.id=z.id_os AND z.do IS NULL; SELECT count(o.id) ilosc INTO l_wydz FROM osoby o, zatrudnienia z,wydzialy w WHERE o.id=z.id_os AND z.do IS NULL AND z.id_wydz=w.id AND w.nazwa=z_wydzial; IF (l_wydz/l_wszyscy)*100 >= 50 THEN RETURN 'Wydzial zatrudnia ponad 50% ogolu zatrudnionych'; ELSIF (l_wydz/l_wszyscy)*100 BETWEEN 25 AND 50 THEN RETURN 'Wydzial zatrudnia ponad 25% ogolu zatrudnionych'; ELSIF (l_wydz/l_wszyscy)*100 BETWEEN 0 AND 25 THEN 17

END IF; RETURN 'Wydzial zatrudnia ponizej 25% ogolu zatrudnionych'; END l_zatrudnionych; z_wydzial wydzialy.nazwa%type:='fizyka'; komentarz VARCHAR2(100); komentarz:=l_zatrudnionych(z_wydzial); DBMS_OUTPUT.PUT_LINE(z_wydzial ' ' komentarz); z_wydzial:='matematyka'; komentarz:=l_zatrudnionych(z_wydzial); DBMS_OUTPUT.PUT_LINE(z_wydzial ' ' komentarz); z_wydzial:='prawo'; komentarz:=l_zatrudnionych(z_wydzial); DBMS_OUTPUT.PUT_LINE(z_wydzial ' ' komentarz); 4. Zaprojektować procedurę zwracającą wartość największej pensji osoby aktualnie zatrudnionej której wypłacanie rozpoczęto w podanym roku. Ponadto procedura ma zwracać wartość największej aktualnie wypłacanej pensji osobie aktualnie zatrudnionej. Obie wartości wydrukować w bloku wywołania. CREATE OR REPLACE PROCEDURE pensja ( z_rok NUMBER ) AS z_pensja pensje.pensja%type; z_naj_pensja pensje.pensja%type; SELECT MAX(p.pensja) pensja INTO z_pensja FROM pensje p, osoby o, zatrudnienia z WHERE o.id=p.id_os AND o.id=z.id_os AND z.do IS NULL AND p.do IS NULL AND TO_NUMBER(TO_CHAR(p.od,'YYYY'))=z_rok; SELECT MAX(p.pensja) pensja INTO z_naj_pensja FROM pensje p, osoby o, zatrudnienia z WHERE o.id=p.id_os AND o.id=z.id_os AND z.do IS NULL AND p.do IS NULL; DBMS_OUTPUT.PUT_LINE(z_pensja ' ' z_naj_pensja); END pensja; pensja(1999); 18

Ćwiczenia 10 (pakiety) 1. Mamy zaprojektować pakiet zawierający (globalnie) dostępne: procedurę wprowadzanie danych nowej osoby do tabeli osoby, procedurę usuwania danych osoby już wprowadzonej do tabeli, przy czym musi ona zawierać obsługę deklarowanego przez użytkownika błędu nie znalezienia rekordu do usunięcia, procedurę ( z pętlą prostą) wyświetlającą listę aktualnie zatrudnionych osób a wydziale wskazanym przez swoją nazwę oraz błąd użytkownika w_osobanieznaleziona. CREATE OR REPLACE PACKAGE osoba AS PROCEDURE dodajosobe ( z_id osoby.id%type, z_nazwisko osoby.nazwisko%type, z_imie1 osoby.imie1%type, z_imie2 osoby.imie2%type, z_data osoby.d_ur%type, z_plec osoby.plec%type ); PROCEDURE usunosobe ( z_id osoby.id%type); w_osobanieznaleziona EXCEPTION; PROCEDURE zatrudnieni ( z_wydzial wydzialy.nazwa%type ); END osoba; --------------------------------------------------------------------------- CREATE OR REPLACE PACKAGE BODY osoba AS PROCEDURE dodajosobe ( z_id osoby.id%type, z_nazwisko osoby.nazwisko%type, z_imie1 osoby.imie1%type, z_imie2 osoby.imie2%type, z_data osoby.d_ur%type, z_plec osoby.plec%type ) AS INSERT INTO osoby(id,nazwisko,imie1,imie2,d_ur,plec) VALUES(z_id,z_nazwisko,z_imie1,z_imie2,z_data,z_plec); EXCEPTION WHEN DUP_VAL_ON_INDEX THEN DBMS_OUTPUT.PUT_LINE('Osoba o podanym id juz istnieje w bazie!'); WHEN OTHERS THEN 19

DBMS_OUTPUT.PUT_LINE('Inny blad!'); END dodajosobe; PROCEDURE usunosobe ( z_id osoby.id%type) AS w_osobanieznaleziona EXCEPTION; DELETE FROM osoby WHERE id=z_id; IF SQL%NOTFOUND THEN RAISE w_osobanieznaleziona; END IF; EXCEPTION WHEN w_osobanieznaleziona THEN DBMS_OUTPUT.PUT_LINE('Osoby o podanym id nie znaleziono w tabeli'); END usunosobe; PROCEDURE zatrudnieni (z_wydzial wydzialy.nazwa%type ) AS z_nazwisko osoby.nazwisko%type; z_imie1 osoby.imie1%type; CURSOR k_osoby IS SELECT o.nazwisko, o.imie1 FROM osoby o,wydzialy w, zatrudnienia z WHERE o.id=z.id_os AND z.id_wydz=w.id AND z.do IS NULL AND w.nazwa=z_wydzial; OPEN k_osoby; LOOP FETCH k_osoby INTO z_nazwisko, z_imie1; EXIT WHEN k_osoby%notfound; DBMS_OUTPUT.PUT_LINE('' z_imie1 ' ' z_nazwisko ''); END LOOP; CLOSE k_osoby; END zatrudnieni; END osoba; 20