Dany jest następujący logiczny schemat bazy danych Systemy baz danych 2 laboratorium Projekt zaliczeniowy FAKTURY POZYCJE PK f_id_faktury PK p_id_pozycji f_data_wystawienia f_data_płatnosci f_czy_zaplacona FK1 p_lp p_f_id_faktury p_nazwa p_ilosc p_cena_jednostkowa p_stawka_vat 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 zadań. W tabelce poniżej przedstawiono zasady oceniania projektu. Ocena Poprawnie wykonane zadania dostateczny 1, 2, 3, 4 dostateczny plus 1, 2, 3, 4, 5, 6 dobry 1, 2, 3, 4, 5, 6, 7 dobry plus 1, 2, 3, 4, 5, 6, 7, 8 bardzo dobry 1, 2, 3, 4, 5, 6, 7, 8, 9 Wszystkie odpowiedzi należy umieścić w pliku tekstowym o nazwie xxx.sql (gdzie xxx to numer indeksu). Poprawne rozwiązania przedstawiono przy każdym zadaniu. Plik z rozwiązaniami należy przesłać na adres maciej.piernik@cs.put.poznan.pl. Termin przesyłania rozwiązań upływa w piątek, 30 stycznia 2015, o godzinie 23:59. Wszystkie rozwiązania zostaną przeanalizowane przez oprogramowanie do wykrywania podobieństw w kodzie źródłowym. W przypadku plagiatu obie prace otrzymują automatycznie ocenę niedostateczną i nie ma znaczenia kwestia oryginalnego autorstwa rozwiązania. Poza wysłaniem projektu drogą mailową należy go jeszcze obronić. Obrona może się odbyć w trakcie zajęć lub w wyznaczonym przez prowadzącego na ostatnich zajęciach terminie.
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. 20 18-MAR-07 25-MAR-07 N 40 09-JUL-07 19-JUL-07 N uaktualnij_faktury; PLSQL procedure successfully completed. 20 18-MAR-07 25-MAR-07 N 11.05 40 09-JUL-07 19-JUL-07 N 6.45 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. 60 15-JAN-08 N 0 20 18-MAR-07 25-MAR-07 N 11.05 40 09-JUL-07 19-JUL-07 N 6.45
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); 60 15-JAN-08 N 0 70 15-JAN-08 29-JAN-08 80 15-JAN-08 29-JAN-08 20 18-MAR-07 25-MAR-07 N 11.05 40 09-JUL-07 19-JUL-07 N 6.45 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_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_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_LICZBA_POZYCJI ---------------- 80 15-JAN-08 29-JAN-08 0