Home > Artikel > Ausgabe 6/2018 > 1:1-Beziehungen

1:1-Beziehungen

  PDF ansehen

  Download PDF und Beispieldatenbank

1:1-Beziehungen können für eine ganze Reihe von Anwendungzwecken sinnvoll sein. Sie können damit beispielsweise die Liefer- und/oder die Rechnungsanschrift für einen Kundendatensatz in eigenen Tabellen speichern, um so verschiedene Ziele zu erreichen: beispielsweise die Anzahl der Felder je Tabelle zu verringern, verschiedene Teile der Daten mit unterschiedlichen Berechtigungen versehen und so weiter. In diesem Artikel schauen wir uns an, wie Sie eine 1:1-Beziehung herstellen und welche Stolpersteine es zu beachten gibt.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1806_11Beziehung.accdb.

Aufbau von 1:1-Beziehungen

Eine 1:1-Beziehung besteht aus zwei Tabellen und ist im Prinzip eine eingeschränkte 1:n-Beziehung. Bei der 1:n-Beziehung können Sie dem Datensatz der Tabelle mit dem Primärschlüsselfeld der Beziehung, also etwa tblKunden, keinen, einen oder mehrere Datensätze der Tabelle mit dem Fremdschlüsselfeld der Beziehung zuweisen, also etwa tblBestellungen. In diesem Fall realisieren wir das über ein Fremdschlüsselfeld, das durch die Definition der Beziehung so angelegt wird, dass dieses Feld nur die Werte des Primärschlüsselfeldes der verknüpften Tabelle annehmen kann.

Bei der 1:1-Beziehung ist das prinzipiell genau das Gleiche, mit einem entscheidenden Unterschied: Das Fremdschlüsselfeld der Beziehung wird so ausgelegt, dass es jeden Wert nur einmal annehmen kann, es erhält also einen eindeutigen Index. Das würde im obigen Beispiel der Kunden und Bestellungen bedeuten, dass wir das Fremdschlüsselfeld KundeID der Tabelle tblBestellungen mit einem eindeutigen Index versehen.

Dann könnten Sie jedem Kunden allerdings nur eine Bestellung zuweisen, was definitiv keinen Sinn ergibt. In anderen Fällen jedoch schon: Wenn Sie etwa die Adresse des Kunden in einer eigenen Tabelle verwalten wollen (zum Beispiel namens tblKundenLieferadresse), würde ein mit einem eindeutigen Index versehenes Feld etwa namens KundeID als Fremdschlüsselfeld durchaus sinnvoll sein. Auf diese Weise ist sichergestellt, dass es für jeden Kunden nur eine Lieferadresse gibt. Was übrigens in den meisten Anwendungsfällen ausreicht – außer, Sie programmieren eine Datenbank für ein Shopsystem wie Amazon, wo ein Kunde auch Bestellungen an andere Empfänger schicken lassen kann.

Auf die gleiche Weise könnte man dann auch noch eine zweite Tabelle per 1:1-Beziehung mit der Tabelle tblKunden verknüpfen, zum Beispiel namens tblKundenRechnungsadressen, um zu jedem Kunden auch noch eine Rechnungsadresse speichern zu können. Auch hier würden wir das Fremdschlüsselfeld mit einem eindeutigen Index versehen.

Sinn von 1:1-Beziehungen

Welchen Sinn und Zweck haben solche 1:1-Beziehungen nun? Der erste ist, dass man eine Tabelle auf diese Weise ein wenig entschlacken kann. Das ist insbesondere wichtig, wenn es der Anwendungsfall tatsächlich erfordert, dass die Tabelle mehr als 255 Felder enthält (was in der Realität nicht oft vorkommen sollte – meist lassen sich dann ähnliche Felder in eine m:n-Tabelle auslagern). Sollte also eine Tabelle tatsächlich mehr als 255 Felder benötigen, legen Sie eine zweite Tabelle an, die per Fremdschlüsselfeld mit eindeutigem Index mit der ersten Tabelle verknüpft wird.

Ein weiterer Anwendungszweck sind Berechtigungen. Wenn Sie zum Beispiel Mitarbeiter in einer Datenbank verwalten, könnte die Tabelle mit den Mitarbeitern auch sensible Daten wie etwa das Gehalt enthalten. Die Mitarbeiterdaten benötigen Sie aber auch für andere Zwecke wir etwa das Zuweisen von Aufgaben. Damit beispielsweise Projektleiter dies tun können, ohne Einblick in die Gehälter der Mitarbeiter nehmen zu können, müssten Sie die Tabellen mit entsprechenden Berechtigungen versehen. Wenn Sie das nicht auf Feldebene tun wollen, können Sie die Tabelle aufteilen und per 1:1-Beziehung verknüpfen und den Teil der Tabelle mit den sensiblen Daten entsprechend schützen.

Zugegeben: Das Thema ist nicht relevant, wenn Sie mit einer reinen Access-Datenbank arbeiten, da diese keine Möglichkeiten zur Vergabe von Berechtigungen bietet. Aber wenn Sie etwa mit dem SQL Server arbeiten, ist dies durchaus einen Alternative. Wenngleich Sie dort natürlich auch auf anderer Ebene sicherstellen können, dass Benutzer nur die für sie relevanten Daten sehen – etwa indem Sie per gespeicherter Prozedur nur solche Daten liefern, die der Benutzer benötigt.

Eine andere Variante, die sich ebenfalls die Verwaltung von Kunden anschneidet, ist die, bei der Personen in eine allgemeine Tabelle geschrieben werden und deren Informationen bezüglich ihrer Rolle, also etwa als Kunde, Mitarbeiter oder Lieferant in separaten Tabellen gespeichert werden. Die Tabelle tblPersonen würde dann nur Informationen wie die Anrede, Vorname, Nachname, Geburtsdatum und andere allgemeine Daten aufnehmen. In weiteren Tabellen wie tblKunden, tblMitarbeiter oder tblLieferanten fügen Sie dann die rollenspezifischen Daten hinzu. Auf diese Weise ist es dann auch einfach, einer Person mehrere Rollen zuzuweisen. Warum sollte ein Mitarbeiter nicht gleichzeitig auch Kunde sein?

1:1-Beziehung erstellen

Wir wir eine 1:1-Beziehung erstellen, schauen wir uns am Beispiel von Kunden und Lieferadressen an. Die Tabelle tblKunden soll allgemeine Daten enthalten, wie sie etwa in einem Shopsystem Verwendung finden wie E-Mail-Adresse, das Kennwort oder das Datum der Aufnahme dieses Kunden in die Datenbank (siehe Bild 1).

Entwurf der Tabelle tblKunden

Bild 1: Entwurf der Tabelle tblKunden

Die Tabelle zum Speichern der Lieferadressen enthält die typischen Felder wie Firma, Vorname, Nachname und die Adressdaten. Zusätzlich enthält sie aber auch noch ein Fremdschlüsselfeld namens KundeID, das wir mit dem Feld KundeID der Tabelle tblKunden verknüpfen wollen. Der Clou hierbei ist, dass wir die Eigenschaft Indiziert auf den Wert Ja (Ohne Duplikate) festlegen (siehe Bild 2).

Entwurf der Tabelle tblKundenLieferadressen

Bild 2: Entwurf der Tabelle tblKundenLieferadressen

Die Beziehung könnten wir nun über den Nachschlagefeld-Assistenten für das zukünftige Fremdschlüsselfeld KundeID erstellen, aber in diesem Fall macht das keinen Sinn. Wir werden später in der Benutzeroberfläche, sprich in den Formularen, keinen Anwendungsfall finden, wo wir ein Nachschlagefeld beziehungsweise Kombinationsfeld benötigen, um den Kunden zu einer Lieferadresse auszuwählen.

In diesem seltenen Fall würde ich also die Beziehung direkt über das Beziehungen-Fenster erstellen, das wir über den Ribbon-Eintrag Datenbanktools|Be­zie­hungen|Beziehungen öffnen.

Hier fügen wir die beiden Tabellen tblKunden und tblKundenLieferadressen per Doppelklick auf die entsprechenden Einträge im Dialog Tabelle anzeigen zum Beziehungen-Fenster hinzu (siehe Bild 3).

Einfügen der Tabellen in das Beziehungen-Fenster

Bild 3: Einfügen der Tabellen in das Beziehungen-Fenster

Beziehung anlegen

Danach legen wir die Beziehung an, indem wir das Feld KundeID von der Tabelle tblKundenLieferadressen auf das Feld KundeID der Tabelle tblKunden ziehen. Es erscheint nun der Dialog Beziehungen bearbeiten, wo Sie weitere Einstellungen vornehmen können (siehe Bild 4).

Definieren der Beziehung

Bild 4: Definieren der Beziehung

Hier aktivieren wir die Option Mit referenzieller Integrität und auch die Option Löschweitergabe an verwandte Datensätze. Die erste sorgt dafür, dass das Fremdschlüsselfeld nur solche Werte aufnehmen kann, die auch im verknüpften Feld KundeID der Tabelle tblKunden enthalten sind. Die zweite sorgt dafür, dass beim Löschen eines Datensatzes der Tabelle tblKunden auch der damit vernküpften Datensatz der Tabelle tblKundenLieferadressen gelöscht wird. Auf diese bleiben keine verwaisten Datensätze in der Tabelle tblKundenLieferadressen übrig.

Sie sehen nun auch direkt, dass Access eine 1:1-Beziehung statt der sonst üblichen 1:n-Beziehung als Beziehungstyp in den Dialog eingetragen hat. Es hat also aufgrund des eindeutigen Indexes für das Fremdschlüsselfeld automatisch erkannt, dass eine 1:1-Beziehung angelegt werden soll.

Damit können wir den Dialog Beziehungen bearbeiten nun schließen und der Beziehungspfeil für diese Beziehung erscheint im Beziehungen-Fenster (siehe Bild 5).

Beziehungspfeil der 1:1-Beziehung

Bild 5: Beziehungspfeil der 1:1-Beziehung

1:1-Beziehung ausprobieren

Nun wollen wir die 1:1-Beziehung ausprobieren, indem wir zunächst einen Datensatz in der Tabelle tblKunden anlegen. Nachdem wir dies getan haben und den Datensatz speichern wollen, erscheint die Fehlermeldung aus Bild 6. Diese besagt, dass wir erst einen Datensatz in der Tabelle tblKundenLieferadressen anlegen müssen, der mit dem neuen Datensatz in Beziehung steht.

Fehlermeldung beim Anlegen des ersten Datensatzes

Bild 6: Fehlermeldung beim Anlegen des ersten Datensatzes

Das irritiert zunächst, aber dann wird klar, dass etwas an der Definition der Beziehung nicht stimmen kann. Dadurch, dass wir weiter oben das Feld KundeID aus der Tabelle tblKundenLieferadressen auf das Feld KundeID der Tabelle tblKunden gezogen haben, haben wir die Beziehung falsch aufgebaut. Korrekt wäre gewesen, den Beziehungspfeil vom Feld der Tabelle mit dem Primärschlüsselfeld auf die Tabelle mit dem Fremdschlüsselfeld zu ziehen. Das holen wir nun nach, indem wir die Beziehung im Beziehungen-Dialog markieren und löschen. Dann legen wir diese wie oben beschrieben neu an. Das Ergebnis ist die umgekehrte Angabe der beiden Tabellen im Dialog Beziehung bearbeiten, wo nun die Tabelle tblKunden unter Tabelle/Abfrage und die Tabelle tblKundenLieferadressen unter Verwandte Tabelle/Abfrage aufgeführt wird (siehe Bild 7).

Geänderte Beziehung

Bild 7: Geänderte Beziehung

Wenn wir nun erneut in die Datenblattansicht der Tabelle tblKunden wechseln, können wir auch den ersten Kundendatensatz anlegen. Und danach müssen wir zwar in der Tabelle tblKundenLieferadressen manuell den Primärschlüsselwert des Kundendatensatzes eintragen, aber zu Testzwecken ist das okay. Gleich schauen wir uns noch an, wie wir das per Abfrage vereinfachen (siehe Bild 8).

Fehler beim Speichern eines Datensatzes in der Tabelle tblKunden

Bild 8: Fehler beim Speichern eines Datensatzes in der Tabelle tblKunden

Test der Löschweitergabe

Da wir nun einen Datensatz eingegeben haben, wollen wir auch gleich noch die Löschweitergabe testen. Das Löschen des Datensatzes aus der Tabelle tblKunden sollte den damit verknüpften Datensatz der Tabelle tblKundenLieferadressen ebenfalls löschen. Das gelingt reibungslos. Wenn Sie die Anzeige von Meldungen für Datenänderungen aktiviert haben, erscheint noch die Rückfrage, ob der Datensatz gelöscht werden soll, obwohl durch die Löschweitergabe auch noch andere Datensätze gelöscht werden.

1:1-Beziehung in Abfragen

Wir wollen das Anlegen der Lieferadresse zu einem Kunden nun etwas vereinfachen, und zwar so, dass wir eine Abfrage anlegen, die beide Tabellen enthält. Dabei fügen wir aus der Tabelle mit dem Primärschlüsselfeld alle Felder zum Abfrageentwurf hinzu und aus der Tabelle tblKundenLieferadressen alle Felder außer dem Primärschlüsselfeld (siehe Bild 9).

Zwei per 1:1-Beziehung verknüpfte Datensätze

Bild 9: Zwei per 1:1-Beziehung verknüpfte Datensätze

Wenn wir in die Datenblattansicht der Abfrage namens qryKundenLieferadressen wechseln, erkennen wir zunächst, dass die beiden Felder namens KundeID mit dem Namen der jeweiligen Tabelle als Präfix versehen wurden. Auf diese Weise unterscheidet die Abfrage die beiden gleichnamigen Felder.

Hier können wir problemlos einen Kunden mit seiner Lieferadresse eingeben, wenn wir dabei von links nach rechts vorgehen.

Nach dem Speichern trägt Access auch automatisch den gleichen Wert in das Primärschlüsselfeld der Tabelle tblKunden und tblKundenLieferadressen ein – wir brauchen hier also nicht manuell einzugreifen, um die Verknüpfung herzustellen (siehe Bild 10).

Eingabe eines Datensatzes in die verknüpften Tabellen per Abfrage

Bild 10: Eingabe eines Datensatzes in die verknüpften Tabellen per Abfrage

Geben wir hier nur Daten für die Felder der Tabelle tblKunden ein, wird zwar das Primärschlüsselfeld dieser Tabelle per Autowert gefüllt, aber das Fremdschlüsselfeld der Tabelle tblKundenLieferadressen bleibt leer. Das liegt schlicht daran, dass zu dem neuen Kunden noch kein Datensatz in der Tabelle tblKundenLieferadressen angelegt wurde (siehe Bild 11).

Kundendatensatz ohne Lieferadresse

Bild 11: Kundendatensatz ohne Lieferadresse

Wenn wir das nachholen, wird auch in diesem Fall das Fremdschlüsselfeld KundeID der Tabelle tblKundenLieferadressen automatisch gefüllt.

Lieferadresse ohne Kunde anlegen

Natürlich können wir auch einmal versuchen, Elemente der Lieferadresse in die Abfrage einzugeben, ohne zuvor einen Eintrag in der Tabelle tblKunden anzulegen (sprich: eines der Felder EMail, Kennwort oder Erfasst am zu füllen). Der Versuch, den Datensatz dann zu speichern, führt allerdings zu dem Fehler aus Bild 12.

Versuch, eine Lieferadresse ohne Kunde anzulegen

Bild 12: Versuch, eine Lieferadresse ohne Kunde anzulegen

Diesen Fehler können wir in der Abfrage nicht verhindern, dazu benötigen wir VBA-Code – und den können wir nicht in Abfragen, sondern nur in Formularen nutzen. Wie das gelingt, schauen wir uns in einem weiteren Artikel namens 1:1-Beziehungen in Formularen an.

Weitere 1:1-Beziehung hinzufügen

Wenn Sie dem Kunden eine Lieferadresse hinzufügen, wollen Sie sicher auch eine Rechnungsadresse bereitstellen.

Das ist kein Problem: Wir kopieren einfach die Tabelle tblKundenLieferadressen in eine neue Tabelle namens tblKundenRechnungsadressen und ändern dort den Namen des Primärschlüsselfeldes von LieferadresseID in RechnungsadresseID. Auch hier sollte das Fremdschlüsselfeld KundeID mit einem eindeutigen Index versehen sein (siehe Bild 13).

Entwurf der Tabelle zum Speichern der Rechnungsadressen

Bild 13: Entwurf der Tabelle zum Speichern der Rechnungsadressen

Die Beziehung zwischen den Tabellen tblKunden und tblKundenRechnungsadressen legen wir nun direkt richtig an, indem wir im Beziehungen-Fenster das Feld KundeID der Tabelle tblKunden auf das Feld KundeID der Tabelle tblKundenRechnungsadressen ziehen und die Eigenschaften für die Beziehung wie bei der anderen 1:1-Beziehung einstellen. Das Ergebnis sieht dann wie in Bild 14 aus.

Hinzufügen der zweiten 1:1-Beziehung

Bild 14: Hinzufügen der zweiten 1:1-Beziehung

Abfrage für Liefer- und Rechnungsadressen

Wenn wir nun eine Abfrage mit den Kundendaten und den Liefer- und den Rechnungsadressen erstellen wollen, fügen wir alle drei Tabellen zum Entwurf einer neuen Abfrage hinzu. Wir ziehen wieder alle Felder der Tabelle tblKunden in das Entwurfsraster der neuen Abfrage. Außerdem fügen wir von den beiden anderen Tabellen alle Felder außer den Primärschlüssel- und Fremdschlüsselfeldern hinzu. Wenn wir nun in die Datenblattansicht wechseln, sehen wir das gleiche Phänomen wie für die beiden Felder KundeID der zuvor beschriebenen Abfrage für alle Felder der beiden Tabellen tblKundenLieferadressen und tblKundenRechnungsadressen. Für das Feld Firma der beiden Tabellen werden im Spaltenkopf die Bezeichnungen tblKundenLieferadressen.Firma und tblKundenRechnungsadressen.Firma verwendet (siehe Bild 15).

Ungünstige Benennung der Feldnamen

Bild 15: Ungünstige Benennung der Feldnamen

Um der Erstellung eines Formulars auf Basis dieser Abfrage vorwegzugreifen: Die hier verwendeten Spaltenüberschriften werden auch als Beschriftungsfelder in das Formular übernommen. Wir können also an dieser Stelle direkt etwas Vorarbeit erledigen, damit wir, falls diese Bezeichnungen in mehr als einem Formular auftauchen, diese Arbeit nicht mehrfach ausführen müssen. Also wechseln wir in den Abfrageentwurf und legen für die Felder der beiden Tabellen tblKundenLieferadressen und tblKundenRechnungsadressen passendere Bezeichnungen fest. Das erledigen Sie mit der Eigenschaft Beschriftung des Eigenschaftenblatts für das entsprechende Feld der Abfrage (siehe Bild 16) – etwa, um für das Feld Firma der Tabelle tblKundenLieferadresse die Bezeichnung Firma (Lieferung) einzustellen.

Anpassung der Feldnamen

Bild 16: Anpassung der Feldnamen

Das macht sich dann auch direkt in der Datenblattansicht der Abfrage bemerkbar (siehe Bild 17).

Neue Beschriftung für den Feldnamen

Bild 17: Neue Beschriftung für den Feldnamen

Weitere Beispiele für 1:1-Beziehungen

Weitere Beispiele sind etwa die Verwaltung von Personen, die verschiedene Ausprägungen annehmen können – also etwa als Mitarbeiter, Kunde oder Lieferant.

Wir schauen uns an dieser Stelle nur zwei von drei Tabellen an, die wir mit der Haupttabelle tblPersonen verknüpfen. Diese Tabelle hat ein Primärschlüsselfeld namens PersonID. Die beiden Tabellen tblMitarbeiter und tblKunden1 statten wir mit je einem Fremdschlüsselfeld namens PersonID aus, für das wir einen eindeutigen Index festlegen. Dieses verknüpfen wir wie oben beschrieben mit dem Primärschlüsselfeld der Tabelle tblPersonen. Dabei ziehen wir wieder das Primärschlüsselfeld auf das zukünftige Fremdschlüsselfeld, sodass zwei 1:1-Beziehungen wie in Bild 18 entstehen.

Herstellen der Beziehungen

Bild 18: Herstellen der Beziehungen

Für das Anlegen von Daten in den Tabellen dieser Beziehung gilt wieder das Gleiche wie oben: Sie müssen erst den Datensatz in der Tabelle tblPersonen anlegen und können erst dann Werte zu den Feldern der Tabellen tblMitarbeiter oder tblKunden1 hinzufügen.

Um dies umgekehrt zu erledigen, müssen Sie ein Formular mit ein paar Zeilen Code ausstatten, die beim Eintragen von Werten in die Tabelle mit dem Fremdschlüsselwert der Beziehung den Datensatz der Tabelle mit dem Primärschlüsselfeld füllen. Wie das gelingt, schauen wir uns im Artikel 1:1-Beziehungen in Formularen an.

Zusammenfassung und Ausblick

Dieser Artikel zeigt, wozu man 1:1-Beziehungen nutzen kann und wie Sie diese definieren. Außerdem erfahren Sie, welche Stolpersteine es dabei zu beachten gilt – zum Beispiel, beim Anlegen der Beziehung den Pfeil immer vom Primärschlüsselfeld zum Fremdschlüsselfeld zu ziehen. Außerdem schauen wir uns an, was geschieht, wenn wir die Daten der beiden Tabellen einer 1:1-Beziehung in einer Abfrage zusammenführen und in welcher Reihenfolge wir die Daten eingeben müssen, ohne beim Speichern Fehler auszulösen.

Einen Schritt weiter gehen wir im Artikel 1:1-Beziehungen in Formularen, wo wir die Daten einer solchen Beziehung in einem Formular anzeigen und per Code dafür sorgen, dass keine Datensätze in der Tabelle mit dem Fremdschlüsselfeld der Tabelle angelegt werden, ohne gleichzeitig die Tabelle mit dem Primärschlüsselfeld zu füllen.