bifroest/beispiele/demo_shop.sql
2026-10-27 08:34:17 +01:00

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;