rechnung

1.1 Weltausschnitt

Mit diesem Beispiel wird der Aufbau einer Datenbank für den Zweck der Rechnungsstellung gezeigt. Ausgangspunkt ist dabei die in der folgenden Abbildung angegebene Rechnung (ursprünglich eine reale, die für diesen Zweck aber anonymisiert wurde), also ein Geschäftsobjekt (business object), was in der Datenmodellierung durchaus oft der Fall ist. Es gelten – neben der üblichen kaufmännischen Semantik von Rechnungen - die folgenden Bedingungen und semantischen Festlegungen:

  • Es gibt noch keine Kunden-Relation. Diese soll bei dieser Gelegenheit angelegt werden.
  • In der Datenbank wird auch festgehalten, wer die Kundschaft bedient hat (Verkäufer). Dies wird auf der Rechnung ausgegeben.
  • TOUR bezeichnet das Auslieferungsteam.
  • KVDAT gibt den Tag an, an dem die Kundschaft im Möbelhaus war und die Ware bestellt hat.
  • Eine Rechnung bezieht sich auf genau einen Auftrag.
  • Für jeden Kunden kann, muss aber nicht, zwischen einer Rechnungs- und einer Lieferanschrift unterschieden werden. Eine Rechnungsanschrift hat jeder Kunde.
  • Die angegebene Telefonnummer ist die der Rechnungsanschrift.

Die Abkürzungen bei Position 1 bedeuten:

  • 889999: Artikelnummer (Nr_Artikel).
  • B/00/EG: Standort der Ware im Lager (STAND).
  • COUCHTISCH 1906 EICHE NATUR – MIT LIFT 125x71 cm: Beschreibung der Ware.


Abbildung 1.1-1:

Eine Rechnung (Typ Möbelhaus)

Grundsätzlich und auch bei dieser Aufgabe ist zu beobachten, dass Modellierer versuchen, auch dynamische Aspekte (Verarbeitung der Daten) mit ins Datenmodell zu integrieren. Insbesondere solche Modellierer, die gerade die Vorlesung Systemanalyse hören oder gehört haben. Dies ist falsch und geht auch nicht. Deshalb folgender Hinweis:

Nur Statik, keine Dynamik!

Datenbanken liefern „nur“ das informationelle Gerüst für die „auf ihr“ ablaufenden Geschäftsprozesse. Es müssen also nicht Vorgänge, Handlungen, usw. (dynamische Aspekte des Weltausschnitts) modelliert werden, dies leistet die Systemanalyse, sondern „Strukturen“ (statische Aspekte).

Diese Aufgabe wird mit unterschiedlichem Komplexitätsgrad in drei Stufen gelöst:

1.2 Stufe 1

Aufgabe Stufe 1 – Grundstruktur:

  • Für jeden Kunden wird nur eine Anschrift, die Rechnungsanschrift, erfasst.
  • Es wird keine historische Komponente berücksichtigt, d.h. alte Rechnungen müssen nicht reproduzierbar sein.
  • Aufgabe Stufe 2 - Adressen
  • Für jeden Kunden werden beliebig viele Adressen erfasst. Jede davon kann Rechnungs- oder Lieferanschrift sein. Bei jeder Rechnung kann eine beliebige Anschrift Liefer- bzw. Rechnungsanschrift sein.
  • Aufgabe Stufe 3 – Zeitachse
  • Die Rechnungen sollen über die Zeit gerettet werden, d.h. es soll möglich sein, beliebige Rechnungen der Vergangenheit zu reproduzieren. Also z.B. eine Rechnung vom 20. November 1997 mit den damaligen Preisen, der damaligen Mehrwertsteuer, usw.

Lösung Stufe 1

Für die Stufe 1 sammeln wir zuerst die Attribute ein und bestimmen die Determinanten und funktionalen Abhängigkeiten (ein bei Geschäftsobjekten sinnvolles Vorgehen):

  • Name: des Kunden
  • Vorname
  • PLZ: der Rechnungsanschrift
  • Ort
  • Straße
  • Telefon: die Angabe auf der Rechnung
  • KNr: Kundennummer. Diese ergänzen wir gleich, da die Erfassung der Kunden ohne eine Kundennummer nicht sinnvoll ist.
  • RechnNr: Rechnungsnummer
  • RechnDatum: Rechnungsdatum
  • Verkäufer: die Angabe des Verkäufers erfolgt auf der Rechnung
  • KVDAT: Hierbei handelt es sich um das Kaufvertragsdatum.
  • TOUR: Dabei handelt es sich um die Angabe des Teams, das mit seinem Fahrzeug die Möbel ausliefert. Eine tiefere Semantik liegt nicht vor.
  • PosNr: Rechnungspositionsnummer
  • ArtikelNr: wird bei den Rechnungspositionen angegeben.
  • Anzahl der Artikel pro Position
  • Stand: Standort der Ware im Lager. Wird bei den Rechnungspositionen angegeben.
  • Beschreibung: der Ware, je Position
  • ZV: Zahlungsvereinbarung
  • Preis: Einzelpreis. Der Preis für die gesamte Position wird berechnet aus Anzahl und Preis.

Der Mehrwertsteuersatz wird im Programm hinterlegt, der Mehrwertsteuerbetrag wird dann daraus und aus der Rechnungssumme berechnet.

1.2.1 Objekte und Beziehungen finden

Was können wir nun, auch unter Berücksichtigung der ja immer vorliegenden Objekt-/Beziehungsstruktur von den Attributen ableiten?

Problemlos zu erkennen sind die Kunden, als Objekte, Objektklasse und als Relation. Identifiziert werden sie durch die KNr. Diese ist hier also erstmals Determinante. Voll funktional abhängig von dieser sind die folgenden Attribute:

  • KNR => Name
  • KNR => Vorname
  • KNR => PLZ
  • KNR => Ort
  • KNR => Straße
  • KNR => Telefon

Für die Adressangaben gilt dies nur, weil wir uns in Stufe 1 mit der Rechnungsanschrift begnügen. Damit ergibt sich die erste Relation:

KUNDEN (#KNr, Name, Vorname, PLZ, Ort, Straße, Telefon)

Diese ist bereits in 5NF. Ähnlich einfach ist das Erkennen der Rechnung als Modellelement. Bei genauerem Hinsehen erkennt man aber, dass es eine Unterscheidung geben muss zwischen Rechnungskopf (identifiziert durch die RechnNr) und den Rechnungspositionen, denn es gibt pro Rechnung mehrere Positionen. Folgende funktionalen Abhängigkeiten bestehen von der Determinante RechnNr:

  • RechnNr => RechnDatum: Es gibt genau ein Rechnungsdatum pro Rechnung bzw. von der Rechnungsnummer kann auf das Rechnungsdatum geschlossen werden.
  • RechnNr => Verkäufer: Da immer nur einer für einen Kaufvertrag zuständig ist und nur einer auf der Rechnung erscheint.
  • RechnNr => Tour: Es gibt ein Team je Rechnung.
  • RechnNr => KVDAT: Es gibt hier genau ein Kaufvertragsdatum je Rechnung.
  • RechnNr => ZV: Die Zahlungsvereinbarung ist je Rechnung eindeutig. Trotz Nachfragen konnte auch keine weitere Semantik (z.B. Abhängigkeit vom gekauften Produkt) festgestellt werden.

Damit ergibt sich eine Relation Rechnungsköpfe:

RECHNUNGSKÖPFE (#RechnNr, RechnDatum, Verkäufer, Tour, KVDAT)

Auch diese ist in 5NF. Die letzten leicht erkennbaren Objekte sind die Artikel. Auch sie werden identifiziert (ArtikelNr) und beschrieben. ArtikelNr ist also Determinante mit folgenden funktional abhängigen Attributen:

  • ArtikelNr => Beschreibung: Wir wollen die Beschreibungstexte als Attributsausprägungen auffassen.
  • ArtikelNr => Preis: Da es sich um den Einzelpreis der Artikel handelt.
  • ArtikelNr => Stand: Standort der Ware im Lager. Für einen Artikel immer derselbe.

Dies führt zu folgender Relation:

ARTIKEL (#ArtikelNr, Beschreibung, Preis, Stand)

Auch hier gibt es keinen Verstoß gegen die 5NF.

1.2.2 Rechnungspositionen – kaufmännische Semantik

Bleiben noch die übrigen Attribute. Sie bewegen sich alle um die Rechnungspositionen herum. Ihre Verarbeitung macht bei ungeübten Modellierern regelmäßig Schwierigkeiten. Hier muss erkannt werden, dass das zu modellierende Realweltphänomen (der Informationsträger) das kaufmännische Konstrukt der Rechnungspositionen ist. Wird dies erkannt, ist der Rest einfach. Rechnungspositionen werden durch eine Attributskombination identifiziert: (RechnNr, PosNr). Folgende funktionalen Abhängigkeiten bestehen:

  • (RechnNr, PosNr) => ArtikelNr: Da es (kaufmännische „Tiefensemantik“!) pro Rechnungsposition nur einen Artikel gibt.
  • (RechnNr, PosNr) => Anzahl: Anzahl der Artikel je Position.

Damit ergibt sich folgende Relation, ebenfalls in 5NF:

RECHNUNGSPOSITIONEN (#(RechnNr, PosNr), ArtikelNr, Anzahl)

1.2.3 Alternativer Weg

Oftmals wird in Übungen obige Relation über den Zusammenhang von Rechnung und Artikeln erkannt. Da es typischerweise pro Rechnung mehrere Artikel gibt und die Artikel auch auf mehreren Rechnungen auftauchen (ein bestimmtes Sofa, das hundert mal verkauft wurde) wird dabei dann zuerst eine Verbindungsrelation mit dem Schlüssel (RechnNr, ArtikelNr) eingerichtet. Wenn dann die Modellierer die Bedeutung der Rechnungspositionen erkennen, wird dieser Ansatz schnell zur obigen Lösung weiterentwickelt.

Zurück zur Aufgabe. Wir haben nun vier Relationen erkannt, die wesentliche Merkmale der Rechnung beschreiben. Zu prüfen sind aber noch die Schlüssel und Fremdschlüssel, d.h. die relationalen Verknüpfungen:

  • Zwischen Kunden und Rechnungsköpfe: Hier liegt sicherlich eine Beziehung vor. Ein Kunde hat hoffentlich viele Rechnungen mit „unserem“ Unternehmen, aber eine Rechnung bezieht sich immer nur auf einen Kunden (kaufmännische Semantik). Diese 1:n - Beziehung soll auf beiden Seiten die Min-/Max-Angabe 1,1 haben, weshalb sie einfach durch die Übernahme der Kundennummer (KNr) in die Relation Rechnungsköpfe festgehalten wird. Damit wäre auch der erste Fremdschlüssel geklärt:

RECHNUNGSKÖPFE (#RechnNr, RechnDatum, Verkäufer, Tour, KVDAT, KNr)

  • Zwischen Kunden und Artikel: Hier gibt es auf der Ebene der Relationen keine direkte Beziehung. Die Beziehung manifestiert sich ja gerade durch die Rechnung und ihre Positionen.
  • Zwischen Kunden und Rechnungspositionen: Auch hier gibt es auf der Ebene der Relationen keine Beziehung. Die Verknüpfung erfolgt über die Rechnung.
  • Zwischen Rechnungsköpfe und Artikel: Dieser Zusammenhang wird über die Rechnungspositionen hergestellt.
  • Zwischen Rechnungsköpfe und Rechnungs­positionen: Diese Beziehung ist fundamental. Es ist eine 1:n - Beziehung, denn eine Rechnung kann mehrere Positionen haben, eine Rechnungsposition gehört aber immer zu einer bestimmten Rechnung. Diese Beziehung wurde aber schon bei der Festlegung des Schlüssels von Rechnungspositionen festgelegt. Es muss lediglich noch die RechnNr als Fremdschlüssel gekennzeichnet werden:

RECHNUNGSPOSITIONEN (#(RechnNr, PosNr), ArtikelNr, Anzahl)

  • Zwischen Artikel und Rechnungspositionen: Hier liegt wiederum eine 1:n - Beziehung vor. Ein Artikel kommt hoffentlich auf vielen Rechnungspositionen vor und eine Rechnungsposition erfasst genau einen Artikel. Die Min-/Max-Angabe von 1,1 auf der Seite der Rechnungspositionen ist hier besonders sinnvoll, denn es hat keinen Sinn, Rechnungspositionen ohne Artikel zu erfassen. Damit kann die Verknüpfung durch Übernahme der ArtikelNr in die Relation Rechnungspositionen eingerichtet werden. Da dies oben schon geschehen ist (falls nicht, würde das Defizit spätestens hier erkannt), muss lediglich noch die Kennzeichnung von ArtikelNr als Fremdschlüssel erfolgen:

RECHNUNGSPOSITIONEN (#(RechnNr, PosNr), ArtikelNr, Anzahl)

1.2.4 Idealstruktur

Die funktionalen Abhängigkeiten in allen Relationen sind bereits geklärt, da ja die Attribute so zu Relationen gruppiert wurden, dass jeweils ein Schlüssel und die von ihm voll funktional abhängigen Attribute zusammen kamen. Da keine überlappenden Schlüssel auftreten, ist die BCNF auch gesichert. Da darüber hinaus die in der vierten und fünften Normalform angesprochenen Probleme nicht auftreten, befinden sich alle Relationen in 5NF.

Die folgende Abbildung zeigt die grafische Darstellung des Datenmodells.


Abbildung 1.2-1:

Datenmodell Rechnungsstellung

Hier noch die textlichen Notationen – im Zusammenhang:

KUNDEN (#KNr, Name, Vorname, PLZ, Ort, Straße, Telefon)

RECHNUNGSPOSITIONEN (#(RechnNr, PosNr), ArtikelNr, Anzahl)

RECHNUNGSKÖPFE (#RechnNr, RechnDatum, Verkäufer, Tour, KVDAT, KNr)

ARTIKEL (#ArtikelNr, Beschreibung, Preis, Stand)

1.3 Stufe 2 - Adressen

In Stufe 2 wird zwischen Liefer- und Rechnungsadresse unterschieden. Ein Kunde kann beliebig viele Adressen haben. Jede kann bei einer Rechnung Liefer- oder Rechnungsadresse sein.

Die alte Relation Kunden fällt dann weg, da es mehr als eine Adresse pro Kunde gibt. Sie wird in die Relationen Kunden_Stufe2 und Adressen aufgeteilt. Einmalig pro Kunde ist weiterhin KNr, Name, Vorname, so dass daraus die neue Kundenrelation entsteht:

Kunden_Stufe2 (#KNr, Name, Vorname

Adressen werden zu einer eigenen Relation. Wir ergänzen einen Schlüssel Adressnummer (AdressNr), denn einen Schlüssel braucht jede Relation:

Adressen (#AdressNr, PLZ, Ort, Straße, Telefon)

Es fehlt noch die Verknüpfung. Die Beziehung ist n:m, denn ein Kunde hat ja mehrere Adressen und unter einer Adresse wohnen u.U. mehrere Kunden (Mehrfamilienhäuser). Wir benötigen also eine Verbindungsrelation:

Kunden-Adressen_Stufe2 (#(KNr, AdressNr))

Beide Attribute wurden gleich als Fremdschlüssel gekennzeichnet. Damit ist im Datenmodell die Beziehung zwischen Kunden und Adressen festgehalten. Bleibt noch zu klären, wie beim Rechnungskopf festgehalten wird, welche Adresse Liefer- und welche Rechnungsadresse ist. Bisher war einfach die KNr als Fremdschlüssel hinterlegt.

Folgende Vorschläge werden an dieser Stelle in Modellierungsprojekten gemacht:

Vorschlag 1: Zwei Attributskombinationen (KNr, LieferadressNr) und (KNr, RechnungsadressNr) in die Relation Rechnungsköpfe. Beide wären dann Fremdschlüssel. Da sie die KNr gemeinsam haben, könnte auch ein überlappender Fremdschlüssel gewählt werden:

Rechnungsköpfe (#RechnNr, RechnDatum, Verkäufer, Tour, KVDAT, (LieferadressNr, (KNr), RechnungsadressNr)

Dieser ist nicht sinnvoll, da dann in allen Fällen, in denen nur eine Adresse vorliegt, semantisch bedingte Leereinträge vorkommen [Anmerkung] .

Vorschlag 2: Zwei Verbindungsrelationen zwischen Rechnungs­köpfe und Kunden. Eine für die Erfassung der Lieferadressen, eine für die Erfassung der Rechnungsadressen:

LIEFERADRESSEN (#(RechnNr, KNr))

RECHNUNGSADRESSEN (#(RechnNr, KNr))

Auch diese Lösung ist nicht sinnvoll, da hier bei der Erstellung der konkreten Rechnung zwei Relationen für die Feststellung der beiden Anschriften abgefragt werden müssen. Außerdem wird die Information, dass eine bestimmte Rechnung Liefer- oder Rechnungsanschrift ist, in die Meta-Ebene, die Relationenbezeichnung verlegt.

Vorschlag 3: Eine einzige Verbindungsrelation, die gleichzeitig die Liefer- und Rechnungsanschrift festhält:

LR-ADRESSEN (#(RechnNr, (KNr, AdressNr)), Adresstyp)

Diese Lösung ist sinnvoll, da eben in vielen Rechnungen nur eine einzige Anschrift angegeben ist (die dann gleichzeitig Liefer- und Rechnungsadresse ist), manchmal aber zwei. KNr und AdressNr sind zusammen(!) Fremdschlüssel.

Zusammen-
gesetzter Fremdschlüssel

Das Attribut Adresstyp hat die Ausprägungen L(ieferadresse) und R(echnungsadresse). R gibt es immer, L nur, falls es eine extra Lieferanschrift gibt. Ansonsten ist die Rechnungsanschrift gleich der Lieferanschrift. Die folgende  Tabelle zeigt zur Verdeutlichung einige Beispielsdaten:

LR-Adressen

RechnNr

KNr

AdressNr

AdressTyp

1001

007

2

L

1001

007

5

R

2002

007

1

R

9999

010

1

R

 

 

 

 


Hier noch das Gesamtmodell nach Stufe 2 in textlicher Notation:

RECHNUNGSPOSITIONEN (#(RechnNr, PosNr), ArtikelNr, Anzahl)

RECHNUNGSKÖPFE (#RechnNr, RechnDatum, Verkäufer, Tour, KVDAT)

ARTIKEL (#ArtikelNr, Beschreibung, Preis, Stand)

neu: KUNDEN_STUFE2 (#KNr, Name, Vorname)

neu: ADRESSEN (#AdressNr, PLZ, Ort, Straße, Telefon)

neu: KUNDEN-ADRESSEN_STUFE2 (#(KNr, AdressNr))

neu: LR-ADRESSEN (#(RechnNr, (KNr, AdressNr)), Adresstyp)

1.4 Zeitliche Dimension

Wir wählen hier die Methode „ Duplizieren zum Rechnungszeitpunkt“ (vgl. Kapitel 17 im Text RM).

Dabei werden bei den Transaktionsdaten (hier die der Rechnungspositionen) die Daten dupliziert, die zum Zeitpunkt der Rechnungsstellung die richtigen sind. So wird aus dem Attribut ArtikelNr das Attribut RZ-ArtikelNr, d.h. Artikelnummer zum Zeitpunkt der Rechnungsstellung (RZ = Rechnungszeitpunkt). Insgesamt ergibt sich:

RECHNUNGSPOSITIONEN (#(RechnNr, PosNr), RZ-ArtikelNr, RZ-Beschreibung, RZ-Preis, RZ-Stand, Anzahl)

Die Relation Artikel bleibt unverändert:

ARTIKEL (#ArtikelNr, Beschreibung, Preis, Stand)

Diese Lösung hat zur Folge, dass bei der Rechnungsstellung immer eine Kopie der Stammdaten erstellt wird, auch wenn sich diese vielleicht nie verändern. Insgesamt ergibt sich bei dieser Lösung folgendes Datenmodell:

RECHNUNGSPOSITIONEN (#(RechnNr, PosNr), RZ-ArtikelNr, RZ-Beschreibung, RZ-Preis, RZ-Stand, Anzahl).

ARTIKEL (#ArtikelNr, Beschreibung, Preis, Stand)

Rechnungsköpfe (#RechnNr, RechnDatum, Verkäufer, Tour, KVDAT)

KUNDEN _Stufe2 (#KNr, Name, Vorname)

ADRESSEN (#AdressNr, PLZ, Ort, Straße, Telefon)

KUNDEN-ADRESSEN_Stufe2 (#(KNr, AdressNr))

LR-ADRESSEN (#(RechnNr, (KNr, AdressNr)), Adresstyp, RZ-Name, RZ-Vorname, RZ-PLZ, RZ-Ort, RZ-Straße, RZ-Telefon)

Dupliziert wird in die Relationen Rechnungspositionen und LR-Adressen. In diesen spiegelt sich die Transaktion wider, hier werden die zum Zeitpunkt der Transaktion aktuellen Attributsausprägungen hinterlegt.