82 lines
3.8 KiB
SQL
82 lines
3.8 KiB
SQL
-- Demo-Datenbank für eine Datenbank-Verbindung (lesender Zugriff über den Datenbank-Treiber für PostgreSQL).
|
|
-- Anlegen: psql postgresql://aiw:aiw@127.0.0.1:55433/postgres -c "CREATE DATABASE demo_shop"
|
|
-- psql postgresql://aiw:aiw@127.0.0.1:55433/demo_shop -f beispiele/demo_shop.sql
|
|
-- Im Workspace unter Einstellungen → MCP-Server → Datenbank hinzufügen: Host localhost, Port 55433, Datenbank demo_shop,
|
|
-- Benutzer shop_leser, Passwort shop-leser-demo, TLS aus (nur lokal).
|
|
|
|
DROP SCHEMA IF EXISTS shop CASCADE;
|
|
CREATE SCHEMA shop;
|
|
COMMENT ON SCHEMA shop IS 'Erfundene Shop-Daten für Tests';
|
|
|
|
CREATE TABLE shop.kunden (
|
|
id serial PRIMARY KEY,
|
|
name text NOT NULL,
|
|
stadt text NOT NULL,
|
|
segment text NOT NULL CHECK (segment IN ('Privat', 'Gewerbe', 'Öffentlich')),
|
|
seit date NOT NULL
|
|
);
|
|
COMMENT ON TABLE shop.kunden IS 'Kundenstamm';
|
|
|
|
CREATE TABLE shop.produkte (
|
|
id serial PRIMARY KEY,
|
|
name text NOT NULL,
|
|
kategorie text NOT NULL,
|
|
listenpreis numeric(10, 2) NOT NULL
|
|
);
|
|
COMMENT ON TABLE shop.produkte IS 'Sortiment mit Listenpreis in Euro';
|
|
|
|
CREATE TABLE shop.bestellungen (
|
|
id serial PRIMARY KEY,
|
|
kunde_id int NOT NULL REFERENCES shop.kunden,
|
|
bestellt_am date NOT NULL,
|
|
status text NOT NULL CHECK (status IN ('offen', 'versendet', 'storniert'))
|
|
);
|
|
COMMENT ON TABLE shop.bestellungen IS 'Bestellköpfe; Positionen in shop.positionen';
|
|
|
|
CREATE TABLE shop.positionen (
|
|
bestellung_id int NOT NULL REFERENCES shop.bestellungen,
|
|
produkt_id int NOT NULL REFERENCES shop.produkte,
|
|
menge int NOT NULL,
|
|
preis numeric(10, 2) NOT NULL,
|
|
PRIMARY KEY (bestellung_id, produkt_id)
|
|
);
|
|
COMMENT ON TABLE shop.positionen IS 'Bestellpositionen mit tatsächlichem Stückpreis (nach Rabatt)';
|
|
|
|
SELECT setseed(0.42);
|
|
|
|
INSERT INTO shop.produkte (name, kategorie, listenpreis) VALUES
|
|
('Laptop Pro 14', 'Hardware', 1499), ('Monitor 27"', 'Hardware', 329), ('Dockingstation', 'Zubehör', 189),
|
|
('Headset Office', 'Zubehör', 79.90), ('Office-Lizenz', 'Software', 129), ('Cloud-Speicher 1 TB', 'Software', 99),
|
|
('Wartungsvertrag', 'Service', 450), ('Schulung (Tag)', 'Service', 890);
|
|
|
|
INSERT INTO shop.kunden (name, stadt, segment, seit)
|
|
SELECT (ARRAY['Müller', 'Schmidt', 'Schneider', 'Fischer', 'Weber', 'Meyer', 'Wagner', 'Becker', 'Hoffmann', 'Koch'])[1 + (g % 10)]
|
|
|| ' ' || (ARRAY['GmbH', 'AG', 'KG', '', 'e.K.'])[1 + (g % 5)],
|
|
(ARRAY['Hamburg', 'München', 'Köln', 'Berlin', 'Leipzig', 'Stuttgart', 'Dresden', 'Bremen'])[1 + floor(random() * 8)::int],
|
|
(ARRAY['Privat', 'Gewerbe', 'Gewerbe', 'Öffentlich'])[1 + floor(random() * 4)::int],
|
|
date '2019-01-01' + floor(random() * 2000)::int
|
|
FROM generate_series(1, 120) g;
|
|
|
|
INSERT INTO shop.bestellungen (kunde_id, bestellt_am, status)
|
|
SELECT 1 + floor(random() * 120)::int,
|
|
date '2025-01-01' + floor(random() * 365)::int,
|
|
(ARRAY['versendet', 'versendet', 'versendet', 'versendet', 'offen', 'storniert'])[1 + floor(random() * 6)::int]
|
|
FROM generate_series(1, 800);
|
|
|
|
INSERT INTO shop.positionen (bestellung_id, produkt_id, menge, preis)
|
|
SELECT DISTINCT ON (b.id, p.id) b.id, p.id, 1 + floor(random() * 5)::int,
|
|
round(p.listenpreis * (1 - (ARRAY[0, 0, 0, 0.05, 0.1])[1 + floor(random() * 5)::int]), 2)
|
|
FROM shop.bestellungen b
|
|
CROSS JOIN LATERAL (SELECT id, listenpreis FROM shop.produkte ORDER BY random() + b.id * 0 LIMIT 1 + floor(random() * 3)::int) p;
|
|
|
|
ANALYZE shop.kunden, shop.produkte, shop.bestellungen, shop.positionen;
|
|
|
|
-- Rolle, die nur lesen darf
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'shop_leser') THEN
|
|
CREATE ROLE shop_leser LOGIN PASSWORD 'shop-leser-demo';
|
|
END IF;
|
|
END $$;
|
|
GRANT CONNECT ON DATABASE demo_shop TO shop_leser;
|
|
GRANT USAGE ON SCHEMA shop TO shop_leser;
|
|
GRANT SELECT ON ALL TABLES IN SCHEMA shop TO shop_leser;
|