Verknüpfungen / Relationen zwischen Tabellen
Eine Verknüpfung / Relation / Beziehung verbindet zwei Tabellen (Grund- und Detailtabelle) asymmetrisch miteinander. Der Detaildatensatz
bezieht sich auf Daten aus der Grundtabelle. Anstelle einer Kopie, welche der Normalisierung widersprechen würde, wird ein
Verweis, ein Fremdschlüssel (foreign key) in eine Spalte der Detailtabelle eingefügt. Der Wert des Fremdschlüssels muß auf eine eindeutige
Zeile innerhalb der Grundtabelle verweisen. Das hiesige System nutzt als Fremdschlüssel ausschließlich die Primärschlüssel der
Grundtabellen.
Bei Datenbanken mit graphischer Oberfläche können Beziehungen durch Ziehen mit der Maus erstellt werden. Standardbrowser lassen
dies nicht zu, so daß hier die folgende Maske die Definition einer Relation erlaubt:
Die Eingaben bedeuten:
- Relationenname: Legt den Namen der Relation fest. Intern wird dieser Name für die Erstellung des Fremdschlüssels verwendet.
Falls bei einem sd:param
-Element das
sd:relation-Attribut mit dem hier definierten Namen der Relation belegt ist, wird ein Eingabefeld für dieses sd:param-Element
als Pulldownfeld ausgegeben.
- Grundtabelle: Dies ist die Tabelle, welche die Grundeinträge enthält. Bei den drei Tabellen Artikel / Vertreter / Umsatz können
Artikel / Vertreter als Grundtabellen fungieren: Zu einem Artikel bzw. zu einem Vertreter gibt es keinen oder mehrere Einträge
in der Detailtabelle 'Umsatz'.
- gezeigter Ausdruck: Hier ist ein Ausdruck festzulegen, der die Spalten der Grundtabelle sowie alle in Sql-Abfragen zulässigen
Funktionen und Operatoren enthalten darf. Das von diesem Ausdruck erzeugte Ergebnis wird später als sichtbarer Wert
für die Pulldownliste ausgegeben. Tatsächlich verwendet wird die ID der ausgewählten Zeile.
- erster / zweiter Sortierausdruck: Es gilt dasselbe wie für den gezeigten Ausdruck. Die hier festgelegten Ausdrücke
sortieren die Pulldownliste. Fehlen beide, so wird alphabetisch nach dem 'gezeigten Ausdruck' sortiert.
- Ausgabefilter: Falls von den Zeilen der Grundtabelle nur eine Teilmenge angezeigt werden soll, kann hier ein Filter notiert
werden. Dieser darf Spalten der Grundtabelle und Konstanten enthalten.
- Detailspalte: Diese Spalte in der Detailtabelle nimmt die Fremdschlüssel-ID auf und muß vom Typ 'int' oder 'bitSet' sein.
- Kaskadierendes Löschen: Wenn dieser Wert auf 'Ja' gesetzt ist, führt das Löschen eines Eintrages aus der Grundtabelle
zum Löschen aller Detaildatensätze. Dies ist bsp. nützlich, falls eine Onlinebestellung einen Stammdatensatz und
mehrere Detaildatensätze umfaßt und der Nutzer die Bestellung abbrechen möchte. In diesem Fall genügt es, nur
den Grunddatensatz zu löschen, so daß alle Detaildatensätze ebenfalls gelöscht werden.
- Hauptrecht notwendig: Falls Nutzer das Recht haben, in Haupt- und Detailtabelle Zeilen zu erstellen und eigene
Datensätze zu editieren, ist es noch möglich, daß ein Nutzer einen Detaildatensatz zu einem Hauptdatensatz hinzufügt / ändert / löscht,
ohne daß er den Hauptdatensatz direkt bearbeiten darf. Wird diese Spalte auf 'Ja' gesetzt, so ist dies nicht mehr möglich:
Beim Verarbeiten des Detaildatensatzes überprüft der Datenbankserver, ob der Nutzer das Recht hat, den zugeordneten
Hauptdatensatz zu editieren. Falls diese Berechtigung fehlt, wird eine Fehlermeldung ausgegeben. Sie weist auf das fehlende
Recht zur Bearbeitung des Hauptdatensatzes hin.
- Filterspalte der Grundtabelle / Filterquelle der Detailtabelle: Beide Einträge ermöglichen zusammen die Festlegung,
daß die Werte einer Auswahlliste (der aktuellen Verknüpfung) in Abhängigkeit von einer anderen Auswahlliste (Filterquelle)
aktualisiert werden.
Beispiel:
- Eine Grundtabelle 'Fahrzeugtypen' mit einer Spalte 'Bezeichnung' und Zeilen: 'Autos', 'Motorräder', 'Fahrräder', 'Lastkraftwagen'.
- Eine zweite Grundtabelle 'Farzeugtypen_Preisspannen' mit zwei Spalten: 'FahrzeugtypenId' verweist auf die erste Grundtabelle, 'Preis_von_bis'
enthält passende Werte: Zu 'Autos' '5.000 - 10.000', '10.000 - 20.000' usw., für Fahrräder '100 - 300', '300 - 600' usw.
- Die Haupttabelle 'Fahrzeuge' enthält für jedes Fahrzeug eine Zeile.
- Eine Spalte 'Fahrzeuge.Typ' erhält eine Relation auf die Tabelle 'Fahrzeugtypen', hier wird der grundsätzliche Typ des Fahrzeugs
festgelegt: Ein Auto, ein Fahrrad, ein Motorrad usw. Diese Relation wird wie gewohnt definiert.
- Eine zweite Spalte 'Fahrzeuge.Preisspanne' erhält eine Relation auf die Tabelle 'Fahrzeugtypen_Preisspannen'. Als
'gezeigter Ausdruck' wird die Spalte 'Preis_von_bis' festgelegt. Ohne weitere Einschränkungen würde diese Liste
immer alle Preisspannen ausgeben, obwohl der Fahrzeugtyp unpassend wäre. Deshalb muß zusätzlich gefiltert werden:
Die Spalte 'Filterspalte der Grundtabelle' wird mit dem Wert 'Farzeugtypen_Preisspannen.FahrzeugtypenId' belegt. Das ist eine Spalte
vom Datentyp 'int' aus der Grundtabelle dieser Relation.
Die Spalte 'Filterquelle der Detailtabelle' wird mit 'Fahrzeuge.Typ' belegt.
Ergebnis: Beim Ändern der Spalte 'Fahrzeuge.Typ' wird die Änderung zum Server geschickt. Der gewählte Wert wird als Filter
für die Spalte 'Farzeugtypen_Preisspannen.FahrzeugtypenId' verwendet, so daß die angezeigte Liste auf die zum gewählten
Fahrzeugtyp passenden Werte eingeschränkt / gefiltert wird.
Beide Spalten sind selbst Beispiele für die Verwendung dieser Eigenschaft: Die erste Spalte wird neu gefüllt, falls für
die Spalte 'Grundtabelle' ein neuer Wert ausgewählt wird. Dann zeigt die Pulldownliste alle Spalten der Grundtabelle
vom Datentyp 'int' an. Die zweite Spalte wird mit den Spalten der Detailtabelle gefüllt, die als Quelle für diese Datenänderung
fungieren können. Dies können auch Spalten mit einer einfachen Relation (per PDownValues) sein.
- weitere Tabellen / weitere Where-Kriterien: Diese beiden Einträge können genutzt werden, um die Grundtabelle mit anderen
Tabellen zu verknüpfen und die zurückgegebenen Zeilen - zusätzlich zur Filterbedingung - weiter einzuschränken. Sind hier
weitere Tabellen definiert, dann wird die Grundtabelle mit 'A' als Alias adressiert. Für weitere Tabellen sollten die Aliasausdrücke
B, C, B1, B2 usw. genutzt werden (D kollidiert mit einem Kürzel bei Datumsfunktionen). Die aus diesen Tabellen stammenden Spalten
können im Feld 'gezeigter Ausdruck' zusätzlich genutzt werden.
Diese Felder sind bsp. nützlich, falls vier Tabellen Firmen / Ausschreibungen / Vorstellungstermine / Bewerber benötigt werden.
Zu einer Firma gibt es mehrere Ausschreibungen, zu einer Ausschreibung schickt bsp. eine Vermittlungsagentur (Kunde von server-daten)
einige Bewerber. Hier ist es sinnvoll, daß bei der Pulldownliste in der Tabelle 'Vorstellungstermine' nicht nur die Ausschreibung,
sondern zusätzlich der Firmenname sichtbar wird. Dies ist wie folgt möglich:
Welcher Verknüpfungstyp verwendet wird, hängt von der Datenstruktur ab. Angezeigt wird hier nicht nur der Ausschreibungstitel,
sondern zusätzlich der Firmenname in Klammern.
Falls ein Where-Kriterium gewünscht wird, so ist dieses ohne das Schlüsselwort 'Where' einzufügen. Es kann sich um eine Bedingung
oder um mehrere, durch die logischen Verknüpfungsoperatoren Or/And/Not verknüpfte Bedingungen handeln.
- Status: Dieses Feld ist normalerweise aktiv. Es zeigt einen Fehler an, falls die Erstellung einer Verknüpfung nach
dem Speichern gescheitert ist. Dies kann bsp. auftreten, falls die Detailtabelle bereits Daten enthält, welche die
Fremdschlüsselbedingung verletzen.
Aus den Eingaben erzeugt das System dreierlei: Zuerst wird eine gespeicherte Prozedur erstellt. Die obigen Eingaben generieren
ungefähr den folgenden Code:
Select A.ArtikelId,
A.A_Name + ' (' + Cast(A.A_Preis as nvarchar(15)) + ')'
As [interner Ausgabename]
From [Name der Kundendatenbank].dbo.Artikel As A
[Where Ausgabefilter, falls definiert]
Order By A.A_Preis Desc
Falls keine Sortierung angegeben ist, wird nach dem festgelegten Ausdruck aufsteigend sortiert. Die Sortierspalte wird nur benötigt,
falls nach weiteren Spalten oder Ausdrücken sortiert werden soll. Beispiel: Gewünscht ist eine Ausgabe von Nachname + Vorname, sortiert nach
dem Eintrittsdatum absteigend, ohne daß das Eintrittsdatum ausgegeben wird.
Bei eindeutigen Artikelnamen wäre die einfachste Form für die obige Relation zwischen der Grundtabelle Artikel und der
Detailtabelle Umsatz:
A_Name
In diesem Fall wird nur der Artikelname alphabetisch sortiert ausgegeben.
Beispiel für einen Ausgabefilter: Eine Tabelle 'Personen' enthält Personendaten von Kunden und Mitarbeitern. Mittels einer einfachen
Relation (Spalte mit Namen 'Typ', Datentyp
int, PDown-Werte '1;Kunde;2;Mitarbeiter') werden Kunden und Mitarbeiter
unterschieden. Eine Tabelle 'Verkäufe' mit Spalten 'Datum', 'Mitarbeiter', 'Kunde' und weiteren Spalten verwendet zwei Relationen
von den Spalten 'Mitarbeiter' und 'Kunde' auf die Tabelle 'Personen'. Für die erste Relation wird als Filter
Typ = 2
für die zweite Relation der Filter
Typ = 1
genutzt. Damit werden bei der ersten Pulldownliste nur Mitarbeiter, bei der zweiten nur Kunden ausgegeben.
Die erzeugte Prozedur wird später immer dann verwendet, wenn die Pulldown-Liste für die Detailspalte benötigt wird. Intern wird
die erste Spalte, also ein Primärschlüsselwert der Grundtabelle, der Detailspalte zugewiesen. Die Prozedur enthält zusätzliche Logik,
um maximal 10 Ergebnisse auszugeben, durch die Liste zu blättern und sie durch einen Filterausdruck einzuschränken.
Zweitens wird eine Fremdschlüssel-Beziehung zwischen den beiden Tabellen erzeugt, welche die referentielle Integrität
der Daten sicherstellt. In der Detailspalte sind anschließend nur Einträge zulässig, welche als Primärschlüssel
in der Grundtabelle definiert sind. Einträge in der Grundtabelle, die in Detailzeilen verwendet werden, können nicht mehr
gelöscht werden, solange Detailzeilen existieren und 'Kaskadierendes Löschen' auf 'Nein' gesetzt ist.
Drittens werden die Views für die Detailtabelle neu erstellt. Anstelle der ID wird der 'gezeigte Ausdruck' ausgegeben und der View
um eine geeignete LeftJoin-Konstruktion auf die Grundtabelle ergänzt.
Sicherheit
Für die Erstellung einer Verknüpfung ist das objektspezifische Add-Recht oder ein stärkeres Recht erforderlich. Der durch die
Verknüpfung erzeugte Fremdschlüssel wird beim Hinzufügen oder Bearbeiten der Detailtabelle immer überprüft, sofern der Status 'active' ist.
Die Pulldown-Listen mit den Werten der Grundtabelle werden angezeigt, falls die Berechtigung zum Lesen der Detailtabelle vorliegt. Es ist
unerheblich, ob der Nutzer das Recht hat, die Daten der Grundtabelle zu lesen. Diese Designentscheidung wurde getroffen, da es keinen Sinn
macht, einem Nutzer zwar das Leserecht für eine Detailtabelle einzuräumen, ihm jedoch für die Spalte mit der Verknüpfung / Relation
nur eine Zahl auszugeben.
Ein Nutzer mit dem Recht, neue Tabellen und Relationen zu erstellen, kann folglich über Verknüpfungen Inhalte anderer Tabellen
auslesen, sofern er die korrekten Spaltennamen kennt. Dies ist zwar mühsam, jedoch nicht prinzipiell ausgeschlossen.
Hinweise
Der 'gezeigte Ausdruck' darf alle Spalten der aktuellen Tabelle sowie Konstanten, Funktionen und Operatoren enthalten, welche auch in
Sql-Abfragen zulässig sind. Der Ausdruck muß eine einzige Ausgabespalte erzeugen. Kommas zum Erstellen mehrerer Ausgabespalten und Unterabfragen
sind hier, im Gegensatz zur Situation bei Abfragen, nicht zulässig. Für die Tabelle wird entweder kein Alias verwendet oder man
nutze 'A' als Alias, falls unter 'weitere Tabellen' die Grundtabelle adressiert werden soll oder Spaltennamen bei mehreren Tabellen
uneindeutig wären. Die Ausgabespalte darf nicht um einen Alias (' As Output') ergänzt werden. Sind zu den aus der Primärtabelle
verwendeten Spalten Multilang-Verzweigungen definiert, so werden diese einschließlich einer hieraus eventuell resultierenden geänderten
Sortierung berücksichtigt.
Für die Sortierausdrücke gelten analoge Einschränkungen. Sie können mit einem der Schlüsselwörter ASC oder DESC enden, letzteres
erzeugt die absteigende Sortierung.

Link zur hiesigen Seite als QR-Code
Kontaktformular:
Schreiben Sie mir und wir bauen gemeinsam Ihre neue Web-Datenbank!
© 2003-2025 Jürgen Auer, Berlin.