PL/SQL podsumowanie. Dany jest następujący logiczny schemat bazy danych

Podobne dokumenty
Systemy baz danych laboratorium Projekt zaliczeniowy

Systemy baz danych 2 laboratorium Projekt zaliczeniowy

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

15. Funkcje i procedury składowane PL/SQL

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

Instrukcje SQL można podzielić na pięć kategorii, które zostały przedstawione w poniższej tabeli.

Struktura bazy danych

Procedury i funkcje składowane

Wykład 8. SQL praca z tabelami 5

Pakiety podprogramów Dynamiczny SQL

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

Wykład 5. SQL praca z tabelami 2

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

Blaski i cienie wyzwalaczy w relacyjnych bazach danych. Mgr inż. Andrzej Ptasznik

DECLARE VARIABLE zmienna1 typ danych; BEGIN

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

Wykład 05 Bazy danych

Rozdział 17. Zarządzanie współbieżnością zadania

Rozdział 17. Zarządzanie współbieżnością zadania dodatkowe

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

Bazy Danych egzamin 9 luty, 2012 rozwiazania

Ćwiczenie 13 PL/SQL. Język PL/SQL procedury, funkcje, pakiety, wyzwalacze

Zaawansowane bazy danych i hurtownie danych semestr I

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

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

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

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

Używany kiedy pełna treść instrukcji SQL jest nieznana przed uruchomieniem programu.

Plan. Formularz i jego typy. Tworzenie formularza. Co to jest formularz? Typy formularzy Tworzenie prostego formularza Budowa prostego formularza

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

Język SQL. Rozdział 8. Język manipulowania danymi DML zadania

1. Wyzwalacze BD (ang. triggers)

1. Połączenie z bazą danych. W wybranym edytorze tworzymy plik sqltest.py i umieszczamy w nim poniższy kod. #!/usr/bin/python3 import sqlite3

Bazy danych. Wykład IV SQL - wprowadzenie. Copyrights by Arkadiusz Rzucidło 1

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

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

Wyzwalacze TWORZENIE WYZWALACZY

Procedury wyzwalane. Rozdział 13. Procedury wyzwalane. Cele stosowania procedur wyzwalanych. Definiowanie procedury wyzwalanej DML

PODSTAWY BAZ DANYCH 13. PL/SQL

Tworzenie tabeli przez select CREATE TABLE PRAC2 AS SELECT P.NAZWISKO, Z.NAZWA FROM PRAC P NATURAL JOIN ZESP Z

1. ELEMENTY JĘZYKA PL/SQL

Bazy danych. dr inż. Arkadiusz Mirakowski

Ćwiczenie 14 autoryzacja

Bloki anonimowe w PL/SQL

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

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

Oracle PL/SQL. Paweł Rajba.

Język DML. Instrukcje DML w różnych implementacjach SQL są bardzo podobne. Podstawowymi instrukcjami DML są: SELECT INSERT UPDATE DELETE

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

Cheatsheet PL/SQL Andrzej Klusiewicz 1/9

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

Język SQL. Rozdział 9. Język definiowania danych DDL, część 2. zadania

Bazy danych. Bazy danych. Podstawy języka SQL. Dr inż. Paweł Kasprowski.

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

Bazy danych. Dr inż. Paweł Kasprowski

Aspekty aktywne baz danych

Bazy Danych i Usługi Sieciowe

BAZY DANYCH Cz III. Transakcje, Triggery

Deklarowanie kursora

Ćwiczenie 13 PL/SQL. Język PL/SQL procedury, funkcje, pakiety, wyzwalacze

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

1. Pobierz plik z diagramem związków encji schematu Uczelnia (MS Visio) oraz plik ze skryptem tworzącym tabele i wypełniający je danymi, z zasobu:

Bazy danych i usługi sieciowe

1. Tworzenie tabeli. 2. Umieszczanie danych w tabeli

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

Język SQL, zajęcia nr 1

Relacji między tabelami klucze obce. Schemat bazy danych, wczytanej z pliku create_tables.sql. Klucz obcy jako ograniczenie dla kolumny

Język PL/SQL Pakiety podprogramów

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

Podstawy technologii WWW

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

Ćwiczenia laboratoryjne nr 11 Bazy danych i SQL.

Sprawdzenie poziomu izolacji transakcji (w aktualnym połączeniu):

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

Multimedialne bazy danych - laboratorium

UPDATE Studenci SET Rok = Rok + 1 WHERE Rodzaj_studiow =' INŻ_ST'; UPDATE Studenci SET Rok = Rok 1 WHERE Nr_albumu IN ( '111345','100678');

Ustawienie na poziomie sesji (działa do zmiany lub zakończenia sesji zamknięcia połączenia).

Kowalski Marcin Wrocław, dn Jaśkiewicz Kamil Bazy Danych 1 Podstawy Projekt Temat: Baza danych do zarządzania projektami

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

SQL> startup pfile=./admin/pfile/initdbx.ora. SQL> create spfile from pfile='$home/admin/pfile/initdbx.ora' create user bolek identified by bolek;

Oracle PL/SQL. Paweł Rajba.

SQL DDL DML TECHNOLOGIE BAZ DANYCH. Wykład 5: Język DDL i DML. Małgorzata Krętowska

Tworzenie raportów XML Publisher przy użyciu Data Templates

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

Instrukcja podwaja zarobki osób, których imiona zaczynają się P i dalsze litery alfabetu zakładamy, że takich osbób jest kilkanaście.

Microsoft SQL Server Podstawy T-SQL

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

Bazy danych wykład szósty Więzy i wyzwalacze. Konrad Zdanowski ( Uniwersytet Kardynała Stefana Bazy danych Wyszyńskiego, wykładwarszawa)

Przykłady najlepiej wykonywać od razu na bazie i eksperymentować z nimi.

Wybór EUROPEAN będzie rozpoznawał dzień przed miesiącem, natomiast US miesiąc przed dniem.

Relacyjne bazy danych. Podstawy SQL

Oracle PL/SQL. Paweł Rajba.

Biuletyn techniczny. Średnia do urlopu liczona wg daty wypłaty w module CDN OPT!MA Płace i Kadry Plus CDN OPT!MA Copyright 2008 COMARCH SA

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

BAZA DANYCH SIECI HOTELI

T-SQL dla każdego / Alison Balter. Gliwice, cop Spis treści. O autorce 11. Dedykacja 12. Podziękowania 12. Wstęp 15

Grupowanie i funkcje agregujące

Wprowadzenie do projektowania i wykorzystania baz danych Relacje

Transkrypt:

Dany jest następujący logiczny schemat bazy danych PLSQL podsumowanie KaŜda faktura jest identyfikowana przez unikalny identyfikator (f_id_faktury). Na fakturze umieszczone są data wystawienia (f_data_wystawienia) oraz data płatności (f_data_platnosci), przy czym data płatności musi być późniejsza niŝ data wystawienia faktury. Z kaŝdą fakturą związana jest flaga oznaczająca, czy dana faktura została juŝ zapłacona (f_czy_zaplacona, pole przyjmuje wartości T i N ). Faktura składa się z pozycji, kaŝda pozycja posiada sztuczny identyfikator (p_id_pozycji) oraz atrybut p_f_id_faktury będący kluczem obcym wskazującym na fakturę, której dotyczy dana pozycja faktury. KaŜda pozycja faktury posiada liczbę porządkową (p_lp), poszczególne pozycje w ramach faktury są numerowane począwszy od liczby 1. Pozycja faktury posiada ponadto swoją nazwę (p_nazwa), ilość zakupionego towaru (p_ilosc), oraz cenę jednostkową (p_cena_jednostkowa) za towar (cena netto za sztukę, kilogram, litr, itp.) Towary opisywane przez pozycje faktur mogą podlegać trzem róŝnym stawkom podatku VAT (p_stawka_vat, pole przyjmuje wartości: 0%, 7%, 15% i 22%). Wykorzystaj skrypt faktury.sql do utworzenia powyŝszych tabel i załadowania przykładowych danych. Następnie, przygotuj odpowiedzi do poniŝszych zadań. 1. Napisz polecenie języka SQL które stworzy perspektywę v_faktury prezentującą, dla kaŝdej faktury, identyfikator faktury, oraz liczbę pozycji faktury i sumaryczne kwoty faktury netto i brutto (dla kaŝdej pozycji naleŝy pomnoŝyć ilość zakupionego towaru przez cenę jednostkową, dla kolumny brutto naleŝy dodatkowo uwzględnić podatek VAT). Nie zapomnij o zaokrągleniu wyniku do dwóch miejsc dziesiętnych. SELECT * FROM v_faktury; F_ID_FAKTURY LICZBA_POZYCJI SUMA_NETTO SUMA_BRUTTO ------------ -------------- ---------- ----------- 30 4 20.93 24.97 20 4 39.19 45.2 40 4 38.87 45.81 50 5 30.93 36.57 10 6 57.49 63.34

2 Napisz anonimowy blok PLSQL zawierający kursor sparametryzowany. Parametrem kursora jest nazwa produktu. Kursor przebiega przez wszystkie faktury zawierające podany produkt i sprawdza, czy dana faktura została juŝ zapłacona. Jeśli nie została zapłacona, to program drukuje identyfikator faktury i liczbę dni spóźnienia z płatnością. Jeśli faktura została zapłacona, to program drukuje identyfikator faktury i datę płatności. W bloku PLSQL otwórz kursor, przekaŝ nazwę produktu przez zmienną środowiskową i wyświetl zawartość kursora za pomocą procedury DBMS_OUTPUT.PUT_LINE() SET SERVEROUTPUT ON VARIABLE produkt VARCHAR2(100) :produkt := 'majonez dekoracyjny'; PLSQL procedure successfully completed. DECLARE...ciało anonimowego bloku PLSQL Faktura 30 została zapłacona w dniu 07-MAJ-07 PLSQL procedure successfully completed. :produkt := 'jajka delikatesowe 10szt.'; PLSQL procedure successfully completed. DECLARE...ciało anonimowego bloku PLSQL Faktura 40 jest niezapłacona od 179 dni PLSQL procedure successfully completed.

3 Dodaj do powyŝszego bloku PLSQL procedurę obsługi błędu polegającego na podaniu nazwy nieistniejącego produktu. SET SERVEROUTPUT ON VARIABLE produkt VARCHAR2(100) :produkt := 'kaszanka delikatesowa'; PLSQL procedure successfully completed. DECLARE...ciało anonimowego bloku PLSQL Produkt kaszanka delikatesowa nie występuje na Ŝadnej fakturze PLSQL procedure successfully completed. 4 Napisz samodzielną funkcję KWOTA_FAKTURY(f_id_faktury NUMBER) która przyjmuje, jako parametr, identyfikator faktury, i zwraca sumaryczną kwotę na fakturze (iloczyn ilości i ceny jednostkowej netto wszystkich pozycji powiększonych o kwoty naleŝnego podatku). Pamiętaj, aby poprawnie zaokrąglić wynik. SELECT f_id_faktury, KWOTA_FAKTURY(f_id_faktury) AS kwota_faktury FROM faktury; F_ID_FAKTURY KWOTA_FAKTURY ------------ ------------- 10 63.34 20 45.2 30 24.97 40 45.81 50 36.57

5 Dodaj do tabeli FAKTURY atrybut f_kara_za_zwloke. Następnie, napisz procedurę o nazwie UAKTUALNIJ_FAKTURY(), która dla wszystkich niezapłaconych faktur przeliczy i uaktualni wartość atrybutu f_kara_za_zwloke. Przyjmij, Ŝe za kaŝdy dzień spóźnienia w płatności faktury naliczana jest kara w wysokości 0.1% (jeden promil, jedna dziesiąta procenta) kwoty netto faktury. Pamiętaj, Ŝe kara za zwłokę naliczana jest z dokładnością do groszy (a nie np. setnych części grosza). Wylicz stan kar na dzień 1 stycznia 2008 roku. F_ID_FAKTURY F_DATA_WY F_DATA_PL F F_KARA_ZA_ZWLOKE ------------ --------- --------- - ---------------- 10 13-JAN-07 27-JAN-07 T 20 18-MAR-07 25-MAR-07 N 30 23-APR-07 07-MAY-07 T 40 09-JUL-07 19-JUL-07 N 50 15-NOV-07 29-NOV-07 T uaktualnij_faktury; PLSQL procedure successfully completed. F_ID_FAKTURY F_DATA_WY F_DATA_PL F F_KARA_ZA_ZWLOKE ------------ --------- --------- - ---------------- 10 13-JAN-07 27-JAN-07 T 20 18-MAR-07 25-MAR-07 N 11.05 30 23-APR-07 07-MAY-07 T 40 09-JUL-07 19-JUL-07 N 6.45 50 15-NOV-07 29-NOV-07 T 6 Dodaj do procedury UAKTUALNIJ_FAKTURY() obsługę błędu polegającego na tym, Ŝe faktura nie posiada Ŝadnych pozycji faktury. W takim przypadku wartością atrybutu f_kara_za_zwloke jest wartość 0. Dodaj nową niezapłaconą fakturę bez pozycji faktury i sprawdź działanie procedury. INSERT INTO faktury (f_id_faktury, f_czy_zaplacona) VALUES (60, 'N'); uaktualnij_faktury; PLSQL procedure successfully completed. F_ID_FAKTURY F_DATA_WY F_DATA_PL F F_KARA_ZA_ZWLOKE ------------ --------- --------- - ---------------- 60 15-JAN-08 N 0 10 13-JAN-07 27-JAN-07 T 20 18-MAR-07 25-MAR-07 N 11.05 30 23-APR-07 07-MAY-07 T 40 09-JUL-07 19-JUL-07 N 6.45 50 15-NOV-07 29-NOV-07 T

7 Stwórz wyzwalacz (lub trzy oddzielne wyzwalacze) który będzie odnotowywał kaŝdą modyfikację tabeli FAKTURA. Zbuduj tablę HISTORIA(id TIMESTAMP, operacja VARCHAR(30)) i umieszczaj tam znacznik czasowy (SYSTIMESTAMP) kaŝdej operacji INSERT, UPDATE, DELETE kierowanej do tabeli FAKTURA oraz nazwę wykonanej operacji. Sprawdź działanie wyzwalacza. INSERT INTO faktury(f_id_faktury, f_data_wystawienia, f_czy_zaplacona) VALUES (70, SYSDATE, 'N'); UPDATE faktury SET f_data_platnosci = f_data_wystawienia + 14 WHERE f_id_faktury = 70; 1 row updated. DELETE FROM faktury WHERE f_id_faktury = 70; 1 row deleted. SQL> SELECT * FROM historia; ID OPERACJA ------------------------------ ----------------------------- 15-JAN-08 01.39.01.461704 AM wstawienie faktury 15-JAN-08 01.39.12.058893 AM modyfikacja faktury 15-JAN-08 01.39.19.286247 AM usunięcie faktury 8 Utwórz sekwencję faktury_seq. Napisz wyzwalacz umoŝliwiający dodawanie nowej faktury bez podania wartości klucza podstawowego (wartość klucza powinna być wczytana z sekwencji przez wyzwalacz, ale tylko w przypadku, gdy uŝytkownik nie podał wartości klucza podstawowego!). INSERT INTO faktury(f_data_wystawienia, f_data_platnosci) VALUES (SYSDATE, SYSDATE + 14); INSERT INTO faktury(f_id_faktury, f_data_wystawienia, f_data_platnosci) VALUES (70, SYSDATE, SYSDATE + 14); F_ID_FAKTURY F_DATA_WY F_DATA_PL F F_KARA_ZA_ZWLOKE ------------ --------- --------- - ---------------- 60 15-JAN-08 N 0 70 15-JAN-08 29-JAN-08 80 15-JAN-08 29-JAN-08 10 13-JAN-07 27-JAN-07 T 20 18-MAR-07 25-MAR-07 N 11.05 30 23-APR-07 07-MAY-07 T 40 09-JUL-07 19-JUL-07 N 6.45 50 15-NOV-07 29-NOV-07 T 8 rows selected.

9 Dodaj do tabeli FAKTURY atrybut f_liczba_pozycji. Zainicjalizuj wartości tego atrybutu we wszystkich krotkach relacji FAKTURY. Stwórz wyzwalacz, który będzie pielęgnował wartość atrybutu f_liczba_pozycji. Po kaŝdej modyfikacji tabeli POZYCJE (dodanie lub usunięcie pozycji) odpowiednio zmodyfikuj atrybut. Uwaga: nie wolno przenosić pozycji faktury między fakturami, wyzwalacz musi zapobiec takiej operacji! SELECT * FROM faktury WHERE f_id_faktury = 80; F_ID_FAKTURY F_DATA_WY F_DATA_PL F F_KARA_ZA_ZWLOKE F_LICZBA_POZYCJI ------------ --------- --------- - ---------------- ---------------- 80 15-JAN-08 29-JAN-08 0 INSERT INTO pozycje (p_id_pozycji,p_f_id_faktury,p_lp,p_nazwa) VALUES (123,80,1,'sałatka śledziowa'); SELECT * FROM faktury WHERE f_id_faktury = 80; F_ID_FAKTURY F_DATA_WY F_DATA_PL F F_KARA_ZA_ZWLOKE F_LICZBA_POZYCJI ------------ --------- --------- - ---------------- ---------------- 80 15-JAN-08 29-JAN-08 1 UPDATE pozycje SET p_f_id_faktury = 40 WHERE p_id_pozycji = 123; UPDATE pozycje SET p_f_id_faktury = 40 WHERE p_id_pozycji = 123 * ERROR at line 1: ORA-20001: Nie wolno przenieść pozycji do innej faktury ORA-06512: at "MIKOLAJ.TRIG_LICZBA_POZYCJI", line 7 ORA-04088: error during execution of trigger 'MIKOLAJ.TRIG_LICZBA_POZYCJI' DELETE FROM pozycje WHERE p_id_pozycji = 123; 1 row deleted. SQL> SELECT * FROM faktury WHERE f_id_faktury = 80; F_ID_FAKTURY F_DATA_WY F_DATA_PL F F_KARA_ZA_ZWLOKE F_LICZBA_POZYCJI ------------ --------- --------- - ---------------- ---------------- 80 15-JAN-08 29-JAN-08 0

10 Napisz pakiet FINANSE składający się z procedury KOPIA_FAKTURY(p_id NUMBER), która dla faktury o podanym identyfikatorze wstawia do tabel FAKTURY i POZYCJE kopię danej faktury (wraz z pozycjami), z identyfikatorami zwiększonymi o 1000 w stosunku do oryginalnych identyfikatorów (faktury i pozycji) funkcji LICZBA_FAKTUR(p_miesiac NUMBER, p_rok NUMBER), która zwraca liczbę faktur wystawionych w danym miesiącu danego roku. Przetestuj działanie stworzonego przez siebie pakietu. finanse.kopia_faktury(10); F_ID_FAKTURY F_DATA_W F_DATA_P F F_LACZNA_KWOTA F_LICZBA_POZYCJI ------------ -------- -------- - -------------- ---------------- 10 060113 060127 T 63,35 6 20 060318 060325 N 4 30 060423 060507 T 24,98 4 40 060709 060719 N 4 50 061115 061129 T 36,58 5 60 070110 070112 T -1 0 90 061231 0 80 070115 070122 0 1010 060113 060127 T SELECT * FROM pozycje WHERE p_f_id_faktury = 1010; P_ID_POZYCJI P_F_ID_FAKTURY P_LP P_NAZWA P_ILOSC P_CENA_JEDNOSTKOWA P_STAWKA_VAT ------------ -------------- ---------- ----------------------------------- ---------- ------------------------------- 1101 1010 2 piwo Lech Pils 1 2,99,22 1102 1010 3 mleko Łaciate 2% UHT 1 1,99,15 1100 1010 1 chleb baltonowski 2 2,54,22 1103 1010 4 wino Chateau de Lussan Cru Artisan 1 39,99,07 1104 1010 5 czipsy X-Lays papryka 1 4,45,22 1121 1010 6 sok jabłkowy Hortex 1l 1 2,99 0 SELECT finanse.liczba_faktur(1,2007) AS liczba_faktur_styczen_2007 FROM dual; LICZBA_FAKTUR_STYCZEN_2007 -------------------------- 2

11 Zmodyfikuj pakiet FINANSE. Procedura KOPIA_FAKTURY powinna sprawdzać, czy w schemacie uŝytkownika występują tabele FAKTURY_KOPIE i POZYCJE_KOPIE (o strukturze identycznej jak struktura oryginalnej tabeli, odpowiednio). Jeśli tabele istnieją, to procedura powinna tam tworzyć kopie faktur i pozycji. Jeśli tabele nie istnieją, to procedura powinna je najpierw stworzyć (dynamiczny SQL). Podczas wstawiania kopii faktur i pozycji naleŝy zachować oryginalne wartości identyfikatorów (a nie zwiększone o 1000, jak w poprzednim ćwiczeniu). SELECT * FROM faktury_kopie; SELECT * FROM faktury_kopie * BŁĄD w linii 1: ORA-00942: tabela lub perspektywa nie istnieje SELECT * FROM pozycje_kopie; SELECT * FROM pozycje_kopie * BŁĄD w linii 1: ORA-00942: tabela lub perspektywa nie istnieje finanse.kopia_faktury(20); Procedura PLSQL została zakończona pomyślnie. SELECT * FROM faktury_kopie; F_ID_FAKTURY F_DATA_W F_DATA_P F F_LACZNA_KWOTA F_LICZBA_POZYCJI ------------ -------- -------- - -------------- ---------------- 20 060318 060325 N SELECT * FROM pozycje_kopie; P_ID_POZYCJI P_F_ID_FAKTURY P_LP P_NAZWA P_ILOSC P_CENA_JEDNOSTKOWA P_STAWKA_VAT ------------ -------------- ---------- ----------------------------------- ---------- ------------------------------- 105 20 1 ogórek zielony 1,5 4,49,22 106 20 2 sałatka porowa,3 5,22 107 20 3 makrela wędzona 3,5 7,99,15 108 20 4 sok jabłkowy Hortex 1l 1 2,99 0 12 Dodaj do pakietu FINANSE zmienną globalną przechowującą liczbę kopii faktur wykonanych w danej sesji. Dodaj do pakietu funkcję LICZBA_KOPII zwracającą zawartość globalnej zmiennej pakietowej. Przetestuj zachowanie się zmiennej podczas tworzenia kopii kilku faktur. SELECT finanse.liczba_kopii FROM dual; LICZBA_KOPII ------------ 0 finanse.kopia_faktury(30); finanse.kopia_faktury(40); Procedura PLSQL została zakończona pomyślnie. SELECT finanse.liczba_kopii FROM dual; LICZBA_KOPII ------------ 2