Recordset-Typen

Wenn Sie lesend oder schreibend auf die Daten von Tabellen und Abfragen unter VBA zugreifen, so steht fast immer ein DAO-Recordset im Mittelpunkt des Geschehens. Dass es von diesem unterschiedliche Varianten gibt, wird dabei gern übersehen. Untersuchen wir hier, welche Typen existieren und wie sie sich in ihrem Verhalten unterscheiden.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1510_DAO_Recordsets.accdb

öffnen eines Recordsets

Der Zugriff auf die Daten einer Tabelle oder Abfrage geschieht unter DAO und VBA immer über ein Recordset, welches auf ein Database-Objekt und seine Methode OpenRecordset geöffnet wird. Access stellt eine Instanz der aktuellen Datenbank über seine Funktion CurrentDb bereit. über sie greifen Sie etwa auf eine Tabelle tblAdressen zu, indem Sie deren Namen der OpenRecordset-Funktion als Parameter übergeben. Im einfachsten Fall sieht das so aus:

Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset_    
                   ("tblAdressen")

Statt direkt eine Tabelle anzugeben, kann auch ein SQL-String eingesetzt werden:

Set rs = CurrentDb.OpenRecordset_
         ("SELECT * FROM tblAdressen")

Das Ergebnis ist dasselbe. Ist der SQL-String sehr komplex und die Schreibarbeit unter VBA damit zu aufwändig, so kommt auch das öffnen eines Recordset über eine Abfrage in Betracht:

Dim qdf As QueryDef
Dim rs As DAO.Recordset
Set qdf = CurrentDb.QueryDefs_
                  ("qryAdressen")
Set rs = qdf.OpenRecordset()

Hier befände sich der SQL-String in der Auswahlabfrage qryAdressen. Das Ergebnis ist auch hier identisch mit dem Ergebnis des über einen SQL-String direkt geöffneten Recordset-Objekts, wie zuvor.

Was bei der ganzen Sache unterschlagen wird, ist der zweite Parameter, der der Methode OpenRecordset übergeben werden kann. Er gibt an, welcher Recordset-Typ von der Methode zurückgegeben werden soll. Dies könnte etwa der Typ Dynaset sein, welcher in der Folge das Bearbeiten der Daten erlaubte:

Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset_    
        ("tblAdressen", dbOpenDynaset)

Was jedoch passiert, wenn Sie diesen Parameter weglassen Welcher Recordset-Typ kommt dabei heraus

Das können Sie ermitteln, indem Sie anschließend die Type-Eigenschaft abfragen:

Debug.Print rs.Type

Sie erhalten damit eine Zahl, die einen der Elemente von RecordsetTypeEnum wiederspiegelt. öffnen Sie den VBA-Objektkatalog, stellen das obere Kombinationsfeld auf DAO ein und navigieren in der Klassenliste zu dieser Enumeration.

Rechts im Methodenfenster finden Sie nun die fünf möglichen Typen. Beim Klick auf einen der Einträge sehen Sie im Beschreibungsfenster ganz unten den Wert der Konstanten. Für unser erstes Beispiel wird der Wert 1 und damit der Typ dbOpenTable ermittelt.

Doch die Annahme, dass bei Weglassen des optionalen Typ-Parameters für OpenRecordset das Ergebnis-Recordset immer vom Typ Table ist, trügt leider. Denn für das zweite Beispiel mit dem SQL-String bekommen Sie den Typ-Wert 2, was dem Dynaset entspricht. Gleiches gilt für das auf die Abfrage geöffnete Recordset. Und auch bei verknüpften Tabellen, die sich in einer anderen Datenbank befinden, stellt DAO den Typ automatisch auf Dynaset ein.

Aus diesem Grund ist es ratsam, den Typ-Parameter grundsätzlich anzugeben. Denn das Verhalten der Recordset-Varianten unterscheidet sich durchaus, wie wir gleich sehen werden.

Recordset-Typ Table

Dieser über den Parameterwert dbOpenTable erhaltene Typ lässt sich ausschließlich für die in der aktuellen Datenbank befindlichen Tabellen verwenden. Verknüpfte Tabellen und Abfragen kommen hier nicht infrage. Andernfalls käme es beim Aufruf zu einer Fehlermeldung. Seine Datensätze sind aktualisierbar, was bedeutet, dass Datenwerte geändert und -zeilen gelöscht oder hinzugefügt werden können.

Da auch der Typ Dynaset dies unterstützt, fragt sich, wofür dieser Typ überhaupt gut ist. Es gibt genau einen Grund: Nur dieser Typ erlaubt den Aufruf der Methode Seek zum schnellen Suchen von Datensätzen auf Felder, die indiziert sind. Dazu später mehr.

Recordset-Typ Dynaset

Mit dem Parameter dbOpenDynaset wird von OpenRecordset dieser Typ zurückgegeben. Auch hier sind die Datensätze bearbeitbar. Allerdings nicht nur für in der aktuellen Datenbank befindliche Tabellen, sondern auch für verknüpfte Tabellen und Abfragen. Bei Letzteren ist allerdings Voraussetzung, dass sie selbst einen aktualisierbaren Aufbau besitzen. öffnen Sie die fragliche Abfrage einfach als Datenblatt und versuchen Sie darin Datensätze zu bearbeiten. Klappt das, so kann auf die Abfrage mit diesem Recordset-Typ zugegegriffen werden. Doch auch nichtaktualisierbare Abfragen verweigern diesen Parameter dbOpenDynaset nicht. Allerdings wird in der Folge beim Editieren von Datensätzen eine Fehlermeldung ausgegeben.

Recordset-Typ Snapshot

Geben Sie dbOpenSnapshot als Typ-Parameter für das Recordset an, so einsteht eine Datenquelle, deren Datensätze nicht bearbeitet werden können. Sie können so sicherstellen, dass nicht aus Versehen Daten von Tabellen verändert werden. Das jedoch ist auch schon der einzige sinnvolle Grund, diesen Typ einzusetzen. Denn die Performance dieses Typs ist, wie wir noch sehen werden, recht mangelhaft

Unter der Haube geschieht technisch nämlich dies: Bei einem Snapshot werden alle Datensätze der Tabelle oder Abfrage komplett in den lokalen Speicher der Daten-Engine eingelesen, während bei einem Dynaset zunächst nur ein Bruchteil ermittelt wird und die weiteren Datensätze erst auf Anfrage eintrudeln. Diese Anfragen entstehen erst durch die Move– und Find-Methoden des Recordsets. Damit wird auch klar, weshalb die Funktion RecordCount des Recordsets, welche die Zahl der Datensätze zurückgibt, bei beiden Typen unterschiedliche Ergebnisse zeigt. Beim Snapshot ist der Wert korrekt, da bereits alle Datensätze im Speicher liegen. Beim Dynaset jedoch erhalten Sie zunächst immer die 1, weil noch kein weiterer Zugriff auf die Datensätze stattfand. Erst nach einem Aufruf von MoveLast stimmt die Zahl.

Besonders katastrophal verhält sich das Snapshot beim Zugriff auf große verknüpfte Tabellen, die in einer Backend-Datenbank auf einem Netzwerk-Share liegen. Da hier die gesamte Tabelle oder das gesamte Abfrageergebnis übertragen werden muss, kann es zu deutlichen Verzögerungen und Performance-Einbrüchen kommen.

Lange Rede, kurzer Sinn: Selten gibt es einen vernünftigen Grund, diesen Typ einzusetzen.

Recordset-Typ ForwardOnly

Das über den Typ-Parameter dbOpenForwardOnly erhaltene Recordset weist ähnliche Einschränkungen auf, wie ein Snapshot. Die Datenquelle ist nicht aktualisierbar. Zu allem überfluss lassen sich darauf noch nicht einmal die Find-Methoden (FindFirst, FindLast, et cetera) anwenden. Allerdings liegt es in der Performance in der Region eines Dynaset, weil hier ebenfalls zunächst nur der erste Datensatz vorliegt und nicht alle Datensätze auf einen Schwung übertragen werden müssen. Man kann sich innerhalb der Datensätze nur in eine Richtung bewegen: vorwärts. Das bedeutet, dass lediglich die Methode MoveNext zur Navigation erlaubt ist, während MovePrevious und sogar MoveLast fehlschlagen.

Mit all diesen Einschränkungen empfiehlt sich der Einsatz dieses Typs überhaupt nicht. Theoretisch könnte die Performance bei Durchlaufen der Datensätze hier die beste sein, das jedoch bestätigt sich unter keinen Umständen.

Der übersicht halber finden Sie in Bild 1 eine Matrix, die die einzelnen Recordset-Typen und deren erlaubte Methoden auflistet. Read bedeutet dabei, dass Werte aus den Datensätzen ausgelesen werden können. Das ist selbstverständlich bei allen Typen der Fall. Beim Modifizieren von Datensätze (Edit– und Update-Methoden) sieht das schon anders aus. Die Find-Methoden FindFirst, FindNext, FindPrevious und FindLast spendieren nur Dynasets und Snapshots. Die recht spezielle Seek-Methode schließlich erlaubt nur das Table-Recordset.

Recordset-Typen und ihre erlaubte Zugriffsmethoden

Bild 1: Recordset-Typen und ihre erlaubte Zugriffsmethoden

Aufsuchen von Datensätzen mit Seek

Während das Suchen innerhalb der Datensätze eines Recordsets über dessen Find-Methoden bereits in einigen Ausgaben von Access Basics behandelt wurde, soll die Seek-Methode hier etwas ausführlicher vorgestellt werden.

Während die Find-Methoden den Inhalt der Datensätze nacheinander Schritt für Schritt mit dem Suchausdruck vergleichen, bis übereinstimmung festgestellt wird, geht Seek einen anderen Weg. Hier wird direkt der Index eines Feldes herangezogen, über den sehr schnell ein Datensatz identifiziert ist.

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access [basics]:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 400 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar