Bild 1: Datenmodell der Beispieldatenbank
Wenn Sie eine Anwendung bereitstellen wollen, die bereits Daten enthält und deren Daten sowohl von Ihnen als auch vom Benutzer der Anwendung erweitert werden sollen, müssen Sie einige Dinge beachten. Wir gehen zur Vereinfachung davon aus, dass nur neue Daten hinzukommen und keine vorhandenen Daten geändert werden – das würde die Aufgabe noch schwieriger gestalten. Als Beispiel soll eine Datenbank mit Produkten dienen, die sowohl aus einem Basiskatalog gefüttert werden, der gelegentlich erweitert wird, als auch vom Benutzer der Anwendung. Wie Sie das überhaupt machen, welche Probleme das mit sich bringt und wie Sie diese lösen, zeigen wir in diesem Beitrag.
Im Beispiel verwenden wir zwei Tabellen, damit die möglichen Probleme schnell deutlich werden: Die Tabelle tblProdukte enthält die Produktdaten sowie die Zuordnung zu einer Kategorie. Die Kategorien werden in der zweiten Tabelle tblKategorien gespeichert (siehe Bild 1). Der Benutzer soll sowohl neue benutzerdefinierte Kategorien als auch Produkte anlegen können. Genauso soll der Basiskatalog von Produkten und Kategorien erweiterbar sein.
Bild 1: Datenmodell der Beispieldatenbank
Angenommen, es gibt im Basiskatalog drei Kategorien mit den Primärschlüsselwerten 1, 2 und 3. Außerdem gibt es einige Produkte, die mit diesen Kategorien verknüpft sind. Nun fügt der Benutzer eine neue Kategorie hinzu, die standardmäßig den nächsten freien Autowert erhält, zum Beispiel den Wert 4, und fügt außerdem einige Produkte hinzu, die mit dieser neuen Kategorie verknüpft sind.
Wenn der Herausgeber der Produktdatenbank nun dem Basiskatalog eine neue Kategorie hinzufügt, wird diese dort ebenfalls den Primärschlüsselwert 4 erhalten. Wenn wir die neuen Daten des Basiskatalogs nun in die bereits vom Anwender geänderte Datenbank übertragen wollen, müssen wir den Primärschlüsselwert einer der Kategorien ändern – entweder für die aus dem Basiskatalog oder für die vom Benutzer hinzugefügte Kategorie.
Da sowohl im Basiskatalog als auch im der vom Benutzer erweiterten Datenbank bereits Produkte enthalten sind, die mit der neuen Kategorie verknüpft sind, müssen wir folglich auch die Fremdschlüsselfelder dieser Einträge anpassen.
Man würde hier wohl die Daten des Benutzers anpassen, damit die Daten des Basiskatalogs in allen Kopien der Anwendung die gleichen Primärschlüsselwerte hat.
Das ist technisch kein Problem, allerdings ist es ein Aufwand, den man sich sparen könnte. Ein Weg ist, GUIDs als Primärschlüsselwerte zu verwenden. Allerdings bringt dies wieder eigene Probleme mit sich, die wir im Beitrag GUIDs im Primärschlüsselfeld nutzen in der folgenden Ausgabe zeigen (www.access-im-unternehmen.de/1278).
Alternative: Eigener Nummernkreis für den Anwender
Also wählen wir einen alternativen Weg: Wir gehen davon aus, dass die Anzahl der Produkte und Kategorien, die dem Basiskatalog hinzugefügt werden, endlich ist und wählen mit ausreichender Sicherheit eine maximale Menge aus – sagen wir 1.000.000.
Wenn der Benutzer einen neuen Produkt-Datensatz anlegt, soll dieser einen Autowert erhalten, der größer als 1.000.000 ist. Wie erledigen wir das
Dazu fügen wir einfach einen Datensatz hinzu, dessen Primärschlüsselfeld den Wert 1.000.000 aufweist. Und keine Sorge: Sie müssen dazu nicht manuell die entsprechende Anzahl Datensätze eingeben. Wir fügen diesen Datensatz gezielt mit einer Prozedur wie der folgenden hinzu:
Public Sub AutowertSetzen() Dim db As DAO.Database Set db = CurrentDb db.Execute "INSERT INTO tblKategorien(KategorieID, Kategorie) VALUES(1000000, 'Dummy')", dbFailOnError End Sub
Die Prozedur führt eine INSERT INTO-Abfrage aus, die einen Datensatz hinzufügt, der den vorgegebenen Wert für das Feld KategorieID enthält. Das ist übrigens die einzige Methode, wie Sie trotz Autowert einen eigenen ID-Wert zu einer Tabelle hinzufügen können – mit der DAO-Methode AddNew ist das nicht möglich.
Wenn der Benutzer nun einen neuen Datensatz zur Tabelle tblKategorien hinzufügt, erhält dieser direkt den nächsthöheren Wert (siehe Bild 2).
Bild 2: Neuer Benutzer-Datensatz
Der Dummy-Datensatz hat nur einen Nachteil: Er erscheint beispielsweise im Nachschlagefeld zur Auswahl einer Kategorie. Wie können wir das ändern Dazu gibt es zwei Möglichkeiten:
- Wir definieren die Datensatzherkunft des Nachschlagefeldes in der Tabelle so, dass dieser Datensatz nicht angezeigt wird oder
- wir löschen den Datensatz vor der Weitergabe einfach wieder – denn solange der Benutzer die Datenbank nicht komprimiert, ist der zuletzt verwendete Autowert immer noch in der Datenbank gespeichert und es wird beim Anlegen eines neuen Datensatzes der nächste Autowert eingetragen (siehe Bild 3).
Bild 3: Neuer Benutzer-Datensatz ohne Dummy-Datensatz
In der ersten Variante stellen wir die Eigenschaft Datensatzherkunft des Feldes KategorieID im Entwurf der Tabelle tblProdukte wie folgt ein:
SELECT [KategorieID], [Kategorie] FROM tblKategorien WHERE NOT KategorieID = 1000000;
Damit erscheint der Eintrag nicht in diesem Nachschlagefeld und auch nicht in Kombinationsfeldern in Formularen, die auf Basis des Nachschlagefeldes angelegt werden (siehe Bild 4).
Bild 4: Anpassen der Datensatzherkunft des Nachschlagefeldes
ID vor Weitergabe löschen
Bei der zweiten Variante legen wir wir mit der oben genannten Prozedur einen Datensatz mit dem Wert 1.000.000 an und löschen diesen direkt wieder.
Dazu erweitern wir die Prozedur AutowertSetzen um die entsprechende DELETE-Anweisung:
Public Sub AutowertSetzen() ... db.Execute "DELETE FROM tblKategorien WHERE KategorieID = 1000000", dbFailOnError End Sub
Da Access sich den höchsten angelegten Autowert merkt, auch wenn man diesen wieder löscht, wird der erste Datensatz des Benutzers in der Tabelle tblKategorien den Primärschlüsselwert 1.000.001 erhalten.
Wie aber können wir sicherstellen, dass der Benutzer die Datenbank nicht komprimiert und damit den Autowert-Zähler zurücksetzt – sodass der Autowert eines neuen Datensatzes für unser Beispiel den Wert 4 liefert
Auch das lässt sich erledigen: Wir verlegen einfach den Aufruf der Prozedur AutowertSetzen an den Start der Anwendung. Allerdings erweitern wir diese noch leicht, indem wir eine Prüfung wie in Listing 1 voranstellen. Hier kontrollieren wir, ob der höchste Wert des Feldes KategorieID kleiner als 1.000.000 ist. Ist das der Fall, wurde die Datenbank offensichtlich komprimiert oder der Autowert wurde noch nicht auf 1.000.000 eingestellt. Also holen wir dies nach, indem wir einen neuen Datensatz mit diesem Autowert hinzufügen und diesen direkt wieder löschen. Damit erhält der erste vom Benutzer zur Tabelle tblKategorien hinzugefügte Datensatz den Wert 1.000.001.
Public Function AutowertSetzen() Dim db As DAO.Database Dim rst As DAO.Recordset Set db = CurrentDb Set rst = db.OpenRecordset("SELECT Max(KategorieID) FROM tblKategorien", dbOpenDynaset) If rst(0) < 1000000 Then db.Execute "INSERT INTO tblKategorien(KategorieID, Kategorie) VALUES(1000000, 'Dummy')", dbFailOnError db.Execute "DELETE FROM tblKategorien WHERE KategorieID = 1000000", dbFailOnError End If End Function
Listing 1: Setzen des Autowertes, wenn dieser nicht hoch genug ist
Diese Prozedur müssen wir nur noch beim Start der Anwendung aufrufen – dazu legen Sie beispielsweise ein Makro namens AutoExec an, das die Makroaktion CodeAusführen enthält und die Funktion AutowertSetzen() aufruft – die Sub-Prozedur müssen Sie dazu in eine Function-Prozedur ändern.
Den Entwurf des Makros finden Sie in Bild 5.
Bild 5: Makro zum Aufrufen der Funktion zum Einstellen des Autowerts
Damit wird auch nach dem Komprimieren direkt wieder 1.000.000 als letzter Autowert eingestellt, wenn der größte Wert des Feldes KategorieID kleiner als 1.000.000 ist.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo