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:

SuchenNeue RelationSpeichernAbbruch



Hilfe
Übersicht
 -    fk_Umsatz_Artikel
 -    fk_Umsatz_Vertreter
Id
Relationenname *
Grundtabelle *
gezeigter Ausdruck *
erster Sortierausdruck
zweiter Sortierausdruck
Ausgabefilter
Detailspalte*
Kaskadierendes Löschen *
Hauptrecht notwendig
Filterspalte der Grundtabelle
Filterquelle der Detailtabelle
weitere Tabellen
weitere Where-Kriterien
Status *
Owner
Protokoll2005-09-15 14:20:27, admin    Liste

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:

    • weitere Tabellen:
      Inner Join Firmen As B On A.FirmenId = B.FirmenId
    • weitere Where: Kann hier leer bleiben.
    • gezeigter Ausdruck:
      A.Ausschreibungstitel + ' (' + B.Firmenname + ')'
    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.


Kontaktformular:

Schreiben Sie mir und wir bauen gemeinsam Ihre neue Web-Datenbank!

Die Erläuterungen zum Datenschutz habe ich gelesen und stimme diesen zu.

© 2003-2018 Jürgen Auer, Berlin.