ADODB: Datenbankinformationen mit OpenSchema

Möchtest Du den gesamten Artikel lesen? Und vielleicht sogar den Artikel im PDF-Format und die Beispieldateien herunterladen? Dann hole Dir den Artikel gleich hier - völlig kostenlos!

Wenn Du per VBA auf eine Datenbank zugreifst, stellt sich manchmal die Frage: Welche Tabellen gibt es eigentlich? Welche Spalten hat eine bestimmte Tabelle und welche Datentypen verwenden diese? Gibt es Indizes oder Primärschlüssel? Die OpenSchema-Methode der Connection-Klasse aus der ADODB-Bibliothek liefert genau solche Metadaten – und zwar unabhängig davon, ob Du mit einer Access-Datenbank oder einem SQL Server arbeitest. In diesem Artikel zeigen wir, wie Du mit OpenSchema die Struktur einer Datenbank abfragen kannst. Dabei stellen wir die wichtigsten Schema-Typen vor und zeigen für jeden ein praktisches Beispiel.

Beispieldatenbank

Die Beispiele dieses Artikels findest Du in der Beispieldatenbank ADODB_OpenSchema.accdb. Diese enthält ein Modul mdlOpenSchema mit allen hier vorgestellten Prozeduren. Die Datenbank enthält außerdem einige Beispieltabellen, auf deren Struktur wir mit OpenSchema zugreifen.

Was ist OpenSchema?

OpenSchema ist eine Methode des Connection-Objekts von ADODB. Sie liefert ein Recordset zurück, das Metadaten über die Struktur der verbundenen Datenbank enthält. Das können Informationen über Tabellen, Spalten, Indizes, Primärschlüssel, gespeicherte Prozeduren und vieles mehr sein.

Der Aufruf sieht grundsätzlich so aus:

Dim rst As ADODB.Recordset
Set rst = cnn.OpenSchema(SchemaTyp)

Der Parameter SchemaTyp ist ein Wert der Enumeration SchemaEnum. Dieser bestimmt, welche Art von Metadaten abgerufen wird.

Optional können wir einen zweiten Parameter Criteria übergeben, um die Ergebnisse einzuschränken – dazu kommen wir weiter unten.

Voraussetzungen

Für die Verwendung von OpenSchema benötigst Du einen Verweis auf die Bibliothek Microsoft ActiveX Data Objects 6.1 Library. Diesen fügst Du im VBA-Editor über Extras|Verweise hinzu (siehe Bild 1).

Verweis auf die ADODB-Bibliothek

Bild 1: Verweis auf die ADODB-Bibliothek

Außerdem benötigst Du ein geöffnetes Connection-Objekt. Innerhalb einer Access-Datenbank kannst Du dafür einfach CurrentProject.Connection verwenden. Für eine Verbindung zum SQL Server erstellst Du ein eigenes Connection-Objekt mit der passenden Verbindungszeichenfolge, wie wir es im Artikel ADODB: Die Connection-Klasse (www.vbentwickler.de/446) beschrieben haben.

Übersicht der wichtigsten Schema-Typen

Die Enumeration SchemaEnum enthält eine große Anzahl von Konstanten. Die folgenden sind in der Praxis besonders relevant:

  • adSchemaTables (20): Listet alle Tabellen und Sichten (Views) der Datenbank auf.
  • adSchemaColumns (4): Liefert alle Spalten aller Tabellen mit Datentyp, Länge und weiteren Informationen.
  • adSchemaIndexes (12): Zeigt alle Indizes der Datenbank mit den zugehörigen Spalten und Eigenschaften an.
  • adSchemaPrimaryKeys (28): Liefert die Primärschlüssel aller Tabellen.
  • adSchemaForeignKeys (27): Zeigt alle Fremdschlüsselbeziehungen zwischen den Tabellen.
  • adSchemaProcedures (16): Listet gespeicherte Prozeduren auf. Bei Access sind dies die gespeicherten Abfragen.
  • adSchemaViews (23): Zeigt die Sichten (Views) der Datenbank an.

In den folgenden Abschnitten stellen wir die wichtigsten dieser Schema-Typen mit je einem vollständigen Codebeispiel vor.

Tabellen einer Datenbank auflisten

Der wohl häufigste Anwendungsfall ist das Auflisten aller Tabellen einer Datenbank. Dazu verwenden wir die Konstante adSchemaTables. Das zurückgegebene Recordset enthält unter anderem die folgenden Felder:

  • TABLE_CATALOG: Name der Datenbank
  • TABLE_SCHEMA: Schema der Tabelle (bei Access meist leer, bei SQL Server zum Beispiel dbo)
  • TABLE_NAME: Name der Tabelle
  • TABLE_TYPE: Art des Objekts, zum Beispiel TABLE, VIEW, SYSTEM TABLE oder ACCESS TABLE

Die Prozedur in Listing 1 gibt alle Tabellen der aktuellen Access-Datenbank im Direktbereich aus.

Public Sub TabellenAuflisten()
    Dim cnn As ADODB.Connection
    Dim rst As ADODB.Recordset
    Dim strConnection As String
    Dim strServer As String
    Dim strDatabase As String
    strServer = "amvDesktop2023"
    strDatabase = "Mitarbeiterverwaltung"
    Set cnn = New ADODB.Connection
    strConnection = "Provider=MSOLEDBSQL;Data Source=" _
        & strServer & ";Initial Catalog=" & strDatabase _
        & ";Integrated Security=SSPI;"
    cnn.Open strConnection
    Set rst = cnn.OpenSchema(adSchemaTables)
    Do While Not rst.EOF
        Debug.Print rst!TABLE_NAME, rst!TABLE_TYPE
        rst.MoveNext
    Loop
    rst.Close
    Set rst = Nothing
    cnn.Close
    Set cnn = Nothing
End Sub

Listing 1: Alle Tabellen der Datenbank auflisten

Im Direktbereich erscheint dann eine Auflistung aller Tabellen mit dem jeweiligen Typ. Dabei wirst Du feststellen, dass neben den von Dir angelegten Tabellen auch Systemtabellen erscheinen, die Access intern verwendet, und Views.

Ergebnisse filtern mit Criteria

Oft benötigst Du nicht alle Informationen, die OpenSchema liefert. In diesem Fall kannst Du den optionalen Parameter Criteria verwenden. Dieser erwartet ein Array mit Filterwerten, wobei die Anzahl und Bedeutung der Array-Elemente vom jeweiligen Schema-Typ abhängt.

Für adSchemaTables akzeptiert Criteria ein Array mit vier Elementen in der folgenden Reihenfolge:

  • TABLE_CATALOG: Datenbankname (oder Null für alle)
  • TABLE_SCHEMA: Schemaname (oder Null für alle)
  • TABLE_NAME: Tabellenname (oder Null für alle)
  • TABLE_TYPE: Tabellentyp (oder Null für alle)

Wenn wir beispielsweise nur die regulären Tabellen anzeigen wollen und keine Systemtabellen oder Sichten, können wir das wie in Listing 2 formulieren.

Public Sub NurTabellen()
    ...
    cnn.Open strConnection
    Set rst = cnn.OpenSchema(adSchemaTables, Array(Null, Null, Null, "TABLE"))
    Do While Not rst.EOF
        Debug.Print rst!TABLE_NAME, rst!TABLE_TYPE
        rst.MoveNext
    Loop
    rst.Close
    Set rst = Nothing
End Sub

Listing 2: Nur benutzerdefinierte Tabellen anzeigen

Hier übergeben wir für die ersten drei Elemente des Arrays den Wert Null, da wir keine Einschränkung für Katalog, Schema oder Tabellenname vornehmen möchten. Das vierte Element setzen wir auf den Wert TABLE, wodurch nur reguläre Tabellen zurückgegeben werden.

Spalten einer Tabelle ermitteln

Mit adSchemaColumns können wir die Spalten einer Tabelle samt Datentyp, Länge und weiteren Eigenschaften abfragen. Das ist besonders nützlich, wenn Du zur Laufzeit die Struktur einer Tabelle analysieren musst – zum Beispiel für einen generischen Export oder eine dynamische Formularerstellung.

Das zurückgegebene Recordset enthält unter anderem diese Felder:

  • COLUMN_NAME: Name der Spalte
  • DATA_TYPE: Numerischer Wert für den Datentyp (entspricht den ADODB-Typkonstanten wie adInteger, adVarWChar und so weiter)
  • CHARACTER_MAXIMUM_LENGTH: Maximale Zeichenlänge bei Textspalten
  • IS_NULLABLE: Gibt an, ob die Spalte Null-Werte erlaubt
  • ORDINAL_POSITION: Position der Spalte in der Tabelle

Der Criteria-Parameter für adSchemaColumns akzeptiert ein Array mit vier Elementen:

TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME und COLUMN_NAME.

In Listing 3 filtern wir die Ergebnisse auf eine bestimmte Tabelle.

Public Sub SpaltenErmitteln()
    ...
    Set rst = cnn.OpenSchema(adSchemaColumns, Array(Null, Null, "tblKunden", Null))
    Do While Not rst.EOF
        Debug.Print rst!COLUMN_NAME, rst!DATA_TYPE, rst!CHARACTER_MAXIMUM_LENGTH
        rst.MoveNext
    Loop
    rst.Close
    Set rst = Nothing
End Sub

Listing 3: Spalten einer Tabelle ermitteln

Die Ausgabe zeigt für jede Spalte den Namen, den numerischen Datentyp und die maximale Zeichenlänge. Bei numerischen Spalten ist die Zeichenlänge Null (siehe Bild 2).

Tabellen einer Datenbank

Bild 2: Tabellen einer Datenbank

Datentyp-Nummern lesbar machen

Die Spalte DATA_TYPE liefert numerische Werte, die den Konstanten der Enumeration DataTypeEnum entsprechen.

Um die Ausgabe lesbarer zu gestalten, können wir eine Hilfsfunktion erstellen, die den numerischen Wert in einen lesbaren Namen umwandelt (siehe Listing 4).

Public Function DatentypName( _
          ByVal lngTyp As Long) As String
     Select Case lngTyp
          Case 2: DatentypName = "SmallInt"
          Case 3: DatentypName = "Integer"
          Case 4: DatentypName = "Single"
          Case 5: DatentypName = "Double"
          Case 6: DatentypName = "Currency"
          Case 7: DatentypName = "Date"
          Case 11: DatentypName = "Boolean"
          Case 17: DatentypName = "Byte"
          Case 72: DatentypName = "GUID"
          Case 130: DatentypName = "Text (WChar)"
          Case 202: DatentypName = "VarWChar"
          Case 203: DatentypName = "LongVarWChar"
          Case 205: DatentypName = "LongVarBinary"
          Case Else
               DatentypName = "Typ " & lngTyp
     End Select
End Function

Listing 4: Hilfsfunktion zum Umwandeln der Datentypen

Diese Funktion kannst Du in der Prozedur SpaltenErmitteln verwenden, indem Du die Zeile mit rst!DATA_TYPE wie folgt anpasst:

Debug.Print rst!COLUMN_NAME,
     DatentypName(rst!DATA_TYPE),
     rst!CHARACTER_MAXIMUM_LENGTH

Damit erhalten wir das Ergebnis aus Bild 3.

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

Schreibe einen Kommentar