From 1f4cf0021ce704ed420bb54c9ed6e438e88c5dcb Mon Sep 17 00:00:00 2001 From: Tim Kainz Date: Sat, 17 May 2025 16:02:20 +0200 Subject: [PATCH] added project --- create_tables.sql | 138 ++++++++++++++++++++++++++++++++++++++++++++++ procedures.sql | 89 ++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 create_tables.sql create mode 100644 procedures.sql diff --git a/create_tables.sql b/create_tables.sql new file mode 100644 index 0000000..09d5e28 --- /dev/null +++ b/create_tables.sql @@ -0,0 +1,138 @@ +DROP TABLE Abteilungen CASCADE CONSTRAINTS; +DROP TABLE Angestellte CASCADE CONSTRAINTS; +DROP TABLE Artikel CASCADE CONSTRAINTS; +DROP TABLE Preishistorie CASCADE CONSTRAINTS; +DROP TABLE Lieferanten CASCADE CONSTRAINTS; +DROP TABLE Lieferung CASCADE CONSTRAINTS; +DROP TABLE Lieferungsdetails CASCADE CONSTRAINTS; +DROP TABLE Adresse CASCADE CONSTRAINTS; + +CREATE TABLE Adresse ( + Id NUMBER GENERATED AS IDENTITY PRIMARY KEY, + Strasse VARCHAR2(60) NOT NULL, + HausNr NUMBER(5) NOT NULL CHECK (HausNr > 0), + Stadt VARCHAR2(60) NOT NULL, + PLZ NUMBER(10) NOT NULL CHECK (PLZ > 0), + Land VARCHAR2(60) NOT NULL +); + +CREATE TABLE Abteilungen ( + Id NUMBER GENERATED AS IDENTITY PRIMARY KEY, + Name VARCHAR2(50) NOT NULL, + AbteilungsleiterId NUMBER +); + +CREATE TABLE Angestellte ( + Id NUMBER GENERATED AS IDENTITY PRIMARY KEY, + Personalnummer NUMBER UNIQUE NOT NULL CHECK (Personalnummer > 0), + Name VARCHAR2(50) NOT NULL, + AdresseId NUMBER NOT NULL, + AbteilungsId NUMBER, + CONSTRAINT fk_adresse FOREIGN KEY (AdresseId) REFERENCES Adresse(Id), + CONSTRAINT fk_abteilung FOREIGN KEY (AbteilungsId) REFERENCES Abteilungen(Id) +); + +CREATE TABLE Artikel ( + Id NUMBER GENERATED AS IDENTITY PRIMARY KEY, + Bezeichnung VARCHAR2(50) NOT NULL, + Verkaufspreis NUMBER NOT NULL CHECK (Verkaufspreis >= 0), + SupermarktArtikelnummer VARCHAR2(50) UNIQUE NOT NULL CHECK (LENGTH(SupermarktArtikelnummer) >= 4), + AbteilungsId NUMBER NOT NULL, + Vorrat Number DEFAULT 0 CHECK (Vorrat >= 0) NOT NULL, + CONSTRAINT fk_artikel_abteilung FOREIGN KEY (AbteilungsId) REFERENCES Abteilungen(Id) +); + +CREATE TABLE Preishistorie ( + Id NUMBER GENERATED AS IDENTITY PRIMARY KEY, + ArtikelId NUMBER NOT NULL, + GueltigAb DATE NOT NULL, + Preis NUMBER NOT NULL, + Typ VARCHAR2(50) NOT NULL CHECK (Typ IN ('Normalpreis', 'Aktionspreis')), + CONSTRAINT fk_preishistorie_artikel FOREIGN KEY (ArtikelId) REFERENCES Artikel(Id) +); + +CREATE TABLE Lieferanten ( + Id NUMBER GENERATED AS IDENTITY PRIMARY KEY, + Name VARCHAR2(50) NOT NULL, + AdresseId NUMBER NOT NULL, + CONSTRAINT fk_lieferanten_adresse FOREIGN KEY (AdresseId) REFERENCES Adresse(Id) +); + +CREATE TABLE Lieferung ( + Id NUMBER GENERATED AS IDENTITY PRIMARY KEY, + LieferantId NUMBER NOT NULL CHECK (LieferantId > 0), + Lieferdatum DATE NOT NULL, + CONSTRAINT fk_lieferung_lieferant FOREIGN KEY (LieferantId) REFERENCES Lieferanten(Id) +); + +CREATE TABLE Lieferungsdetails ( + Id NUMBER GENERATED AS IDENTITY PRIMARY KEY, + LieferungsId NUMBER NOT NULL, + ArtikelId NUMBER NOT NULL, + Kaufpreis NUMBER NOT NULL CHECK (Kaufpreis >= 0), + Menge NUMBER NOT NULL CHECK (Menge > 0), + LieferantArtikelnummer VARCHAR2(50) NOT NULL, + CONSTRAINT fk_lieferungsdetails_lieferung FOREIGN KEY (LieferungsId) REFERENCES Lieferung(Id), + CONSTRAINT fk_lieferungsdetails_artikel FOREIGN KEY (ArtikelId) REFERENCES Artikel(Id) +); + +--INSERTS + +--Daten für die Tabelle Adresse +INSERT INTO Adresse (Strasse, HausNr, Stadt, PLZ, Land) VALUES ('Hauptstraße', 1, 'Wien', 1010, 'Österreich'); +INSERT INTO Adresse (Strasse, HausNr, Stadt, PLZ, Land) VALUES ('Bahnhofstraße', 15, 'Linz', 4020, 'Österreich'); +INSERT INTO Adresse (Strasse, HausNr, Stadt, PLZ, Land) VALUES ('Marktplatz', 3, 'Salzburg', 5020, 'Österreich'); + +--Daten für die Tabelle Abteilungen +INSERT INTO Abteilungen (Name) VALUES ('Milchprodukte'); +INSERT INTO Abteilungen (Name) VALUES ('Backwaren'); +INSERT INTO Abteilungen (Name) VALUES ('Süßes'); + +--Daten für die Tabelle Angestellte +INSERT INTO Angestellte (Personalnummer, Name, AdresseId, AbteilungsId) VALUES (1001, 'Matthias Watzinger', 1, 1); +INSERT INTO Angestellte (Personalnummer, Name, AdresseId, AbteilungsId) VALUES (1002, 'Anna Schmidt', 2, 2); +INSERT INTO Angestellte (Personalnummer, Name, AdresseId, AbteilungsId) VALUES (1003, 'Felix Huber', 3, 3); + +--Daten für die Tabelle Artikel +INSERT INTO Artikel (Bezeichnung, Verkaufspreis, SupermarktArtikelnummer, AbteilungsId, Vorrat) VALUES ('Milch', 1.29, 'A1001', 1, 10); +INSERT INTO Artikel (Bezeichnung, Verkaufspreis, SupermarktArtikelnummer, AbteilungsId, Vorrat) VALUES ('Brot', 2.49, 'A1002', 1, 5); +INSERT INTO Artikel (Bezeichnung, Verkaufspreis, SupermarktArtikelnummer, AbteilungsId, Vorrat) VALUES ('Haribo Gummibärchen', 2.99, 'A1003', 1, 100); + +--Daten für die Tabelle Preishistorie +INSERT INTO Preishistorie (ArtikelId, GueltigAb, Preis, Typ) VALUES (1, TO_DATE('2024-01-01', 'YYYY-MM-DD'), 1.19, 'Aktionspreis'); +INSERT INTO Preishistorie (ArtikelId, GueltigAb, Preis, Typ) VALUES (2, TO_DATE('2024-02-01', 'YYYY-MM-DD'), 2.39, 'Normalpreis'); +INSERT INTO Preishistorie (ArtikelId, GueltigAb, Preis, Typ) VALUES (3, TO_DATE('2024-03-01', 'YYYY-MM-DD'), 2.79, 'Aktionspreis'); + +--Daten für die Tabelle Lieferanten +INSERT INTO Lieferanten (Name, AdresseId) VALUES ('Frisch & Gut GmbH', 1); +INSERT INTO Lieferanten (Name, AdresseId) VALUES ('Bäckerei Sonnenschein', 2); +INSERT INTO Lieferanten (Name, AdresseId) VALUES ('Dairy Fresh AG', 3); + +--Daten für die Tabelle Lieferung +INSERT INTO Lieferung (LieferantId, Lieferdatum) VALUES (1, TO_DATE('2024-03-15', 'YYYY-MM-DD')); +INSERT INTO Lieferung (LieferantId, Lieferdatum) VALUES (2, TO_DATE('2024-03-16', 'YYYY-MM-DD')); +INSERT INTO Lieferung (LieferantId, Lieferdatum) VALUES (3, TO_DATE('2024-03-17', 'YYYY-MM-DD')); + +--Daten für die Tabelle Lieferungsdetails +INSERT INTO Lieferungsdetails (LieferungsId, ArtikelId, Kaufpreis, Menge, LieferantArtikelnummer) VALUES (1, 1, 0.99, 100, 'L1001'); +INSERT INTO Lieferungsdetails (LieferungsId, ArtikelId, Kaufpreis, Menge, LieferantArtikelnummer) VALUES (1, 2, 3, 50, 'L1001'); +INSERT INTO Lieferungsdetails (LieferungsId, ArtikelId, Kaufpreis, Menge, LieferantArtikelnummer) VALUES (2, 2, 1.99, 50, 'L1002'); +INSERT INTO Lieferungsdetails (LieferungsId, ArtikelId, Kaufpreis, Menge, LieferantArtikelnummer) VALUES (3, 3, 2.49, 75, 'L1003'); + +--ALTER und UPDATEs +UPDATE Abteilungen SET AbteilungsleiterId = 1 WHERE Id = 1; -- Matthias Watzinger as Leiter of Milchprodukte +UPDATE Abteilungen SET AbteilungsleiterId = 2 WHERE Id = 2; -- Anna Schmidt as Leiter of Backwaren +UPDATE Abteilungen SET AbteilungsleiterId = 3 WHERE Id = 3; -- Felix Huber as Leiter of Süßes; + +ALTER TABLE Abteilungen +ADD CONSTRAINT fk_abteilungsleiter FOREIGN KEY (AbteilungsleiterId) REFERENCES Angestellte(Id); + +--SELECT (Grundlegend) +SELECT * FROM Adresse; +SELECT * FROM Abteilungen; +SELECT * FROM Angestellte; +SELECT * FROM Artikel; +SELECT * FROM Preishistorie; +SELECT * FROM Lieferanten; +SELECT * FROM Lieferung; +SELECT * FROM Lieferungsdetails; \ No newline at end of file diff --git a/procedures.sql b/procedures.sql new file mode 100644 index 0000000..9d54091 --- /dev/null +++ b/procedures.sql @@ -0,0 +1,89 @@ +SET SERVEROUTPUT ON; +CREATE OR REPLACE PACKAGE supermarkt AS + TYPE product_record IS RECORD ( + product_id NUMBER, + price NUMBER, + amount NUMBER, + supplier_article_number VARCHAR2(50) + ); + TYPE product_collection IS TABLE OF product_record INDEX BY BINARY_INTEGER; + PROCEDURE new_delivery(supplier_id NUMBER, delivery_date DATE, products product_collection); + PROCEDURE change_price(product_id NUMBER, price NUMBER, from_date DATE, special_offer SMALLINT); + FUNCTION get_delivery_price(delivery_id NUMBER) RETURN Number; + FUNCTION get_price_of_date(product_id NUMBER, p_date DATE) RETURN Number; +END supermarkt; +/ +CREATE OR REPLACE PACKAGE BODY supermarkt AS + PROCEDURE new_delivery(supplier_id NUMBER, delivery_date DATE, products product_collection) + IS + begin + INSERT INTO LIEFERUNG (LieferantId, Lieferdatum) + VALUES (supplier_id, delivery_date); + + FOR i IN 1 .. products.COUNT LOOP + INSERT INTO lieferungsdetails (LIEFERUNGSID, ArtikelId, Kaufpreis, Menge, LieferantArtikelnummer) + VALUES ((SELECT Max(Id) FROM LIEFERUNG), products(i).product_id, products(i).price, products(i).amount, products(i).supplier_article_number); + UPDATE Artikel SET Vorrat = Vorrat + products(i).amount WHERE Id = products(i).product_id; + END LOOP; + COMMIT; + end new_delivery; + + PROCEDURE change_price(product_id NUMBER, price NUMBER, from_date DATE, special_offer SMALLINT) + IS + v_price_at_date NUMBER; + v_typ_at_date VARCHAR2(50); + v_count NUMBER; + BEGIN + SELECT COUNT(*) INTO v_count FROM PREISHISTORIE WHERE ARTIKELID = product_id AND TRUNC(GueltigAb) = TRUNC(from_date); + DBMS_OUTPUT.PUT_LINE('Anzahl der Einträge: ' || v_count); + IF v_count > 0 THEN + UPDATE PREISHISTORIE SET Preis = price, Typ = CASE WHEN special_offer = 1 THEN 'Aktionspreis' ELSE 'Normalpreis' END + WHERE ArtikelId = product_id AND TRUNC(GueltigAb) = TRUNC(from_date); + ELSE + INSERT INTO Preishistorie (ArtikelId, GueltigAb, Preis, Typ) + VALUES (product_id, from_date, price, CASE WHEN special_offer = 1 THEN 'Aktionspreis' ELSE 'Normalpreis' END); + + UPDATE Artikel SET Verkaufspreis = get_price_of_date(product_id, SYSDATE) WHERE Id = product_id; + END If; + EXCEPTION + WHEN NO_DATA_FOUND THEN + RAISE_APPLICATION_ERROR(-20001, 'Artikel mit ID ' || product_id || ' nicht gefunden.'); + END change_price; + FUNCTION get_delivery_price(delivery_id NUMBER) RETURN Number + IS + v_total_price Number; + BEGIN + SELECT SUM(Kaufpreis * Menge) INTO v_total_price + FROM lieferungsdetails + WHERE lieferungsid = delivery_id; + RETURN v_total_price; + END get_delivery_price; + FUNCTION get_price_of_date(product_id NUMBER, p_date DATE) RETURN NUMBER + IS + v_price NUMBER; + BEGIN + SELECT Preis INTO v_price + FROM Preishistorie + WHERE ArtikelId = product_id AND GueltigAb <= p_date + ORDER BY GueltigAb DESC + FETCH FIRST 1 ROW ONLY; + RETURN v_price; + END get_price_of_date; + +END supermarkt; +/ +DECLARE + products supermarkt.product_collection := supermarkt.product_collection(); +BEGIN + products(1):= supermarkt.product_record(1, 2.99, 10, 'A123'); + supermarkt.new_delivery(1, SYSDATE, products); + supermarkt.change_price(1, 3.80, SYSDATE+10, 1); + DBMS_OUTPUT.PUT_LINE(supermarkt.get_delivery_price(1)); + DBMS_OUTPUT.PUT_LINE('Aktueller Preis '||supermarkt.get_price_of_date(1,SYSDATE)); + DBMS_OUTPUT.PUT_LINE('Preis nach Änderung '||supermarkt.get_price_of_date(1,SYSDATE+11)); +END; +/ +SELECT * FROM Lieferung; +SELECT * FROM LIEFERUNGSDETAILS; +SELECT * FROM Artikel; +SELECT Preis, TO_CHAR(GUELTIGAB, 'dd.mm.yyyy.hh.ss') FROM PREISHISTORIE WHERE ARTIKELID = 1; \ No newline at end of file