SQL Server-Tabellenverknüpfungsassistent

Herstellen einer Tabellenverknüpfung mit Bordmitteln

Bild 1: Herstellen einer Tabellenverknüpfung mit Bordmitteln

Die Bordmittel von Access zum Herstellen oder Aktualisieren von Tabellenverknüpfungen zum SQL Server sind teilweise etwas umständlich zu bedienen und erfordern zwangsläufig den Einsatz von Data Source Names (DSN). Diese möchte man unter Umständen aber gar nicht nutzen, sondern einfach alle Informationen in die Verbindungszeichenfolge für die Tabelle schreiben. Natürlich kann man sich ein Set von Tabellen und Formularen zusammenstellen, mit denen man die Verbindungszeichenfolgen und Tabellenverknüpfungen verwaltet. Und die man bei Bedarf zu der Datenbank hinzufügt, deren Tabellenverknüpfungen man pflegen möchte. Aber manchmal möchte man einfach nur schnell mal etwas ausprobieren und dazu ist der Aufwand, die Datenbank um diese Tools zu erweitern, zu aufwendig. Wie wäre es also, wenn wir diese Tools einfach in ein Access-Add-In auslagern, mit dem wir unsere Verbindungszeichenfolgen und Verknüpfungen verwalten können? In diesem Beitrag schauen wir uns an, wie dies aussieht.

Anlass zur Programmierung dieses Access-Add-Ins war der Umstand, dass ich immer wieder mal Testdatenbanken vom Kunden bekomme oder selbst Beispiele programmiere, deren Daten im SQL Server liegen und für die ich schnell eine Tabellenverknüpfung erstellen möchte. Das ist mir allerdings über den Assistenten zum Importieren oder Verknüpfen von Tabellen aus ODBC-Datenbanken etwas zu aufwendig (siehe Bild 1).

Herstellen einer Tabellenverknüpfung mit Bordmitteln

Bild 1: Herstellen einer Tabellenverknüpfung mit Bordmitteln

Ich möchte einmal die Verbindungszeichenfolge festlegen und dann so schnell wie möglich Tabellenverknüpfungen erstellen oder aktualisieren.

Tabellen per Add-In verknüpfen

Das gelingt mit dem Access-Add-In, das wir in diesem Beitrag vorstellen, ganz einfach.

Dazu brauchen wir nur über den Ribbon-Befehl Datenbanktools|Add-Ins|Add-Ins|amvTableLinker das Hauptformular unseres Add-Ins zu starten, das direkt nach dem Aufruf wie in Bild 2 aussieht. Hier finden wir nur wenige Elemente vor:

Hauptformular unseres Access-Add-Ins

Bild 2: Hauptformular unseres Access-Add-Ins

  • Das Kombinationsfeld oben zeigt alle Datenbankverbindungen an, die wir bereits im Add-In hinterlegt haben und dient zur Auswahl der zu verwendenden Datenbankverbindung.
  • Das Listenfeld zeigt alle Tabellen und Views an, die wir in der referenzierten Datenbank vorfinden. Das Listenfeld erlaubt die Auswahl mehrerer Tabellen gleichzeitig. Dies geschieht bei gedrückter Alt-Taste, um einzelne Einträge aus- oder abzuwählen und bei gedrückter Umschalttaste lassen sich mehrere zusammenhängende Tabellen markieren.
  • Die Schaltfläche Tabellen verknüpfen verknüpft schließlich alle aktuell markierten Tabellen.

Eine weitere Funktion ist, dass das Listenfeld alle Tabellenverknüpfungen, die es in der Access-Datenbank vorfindet, bereits markiert.

Um alle aktuell vorhandenen Tabellenverknüpfungen zu aktualisieren, braucht man also nur die richtige Verbindungszeichenfolge auszuwählen und die Schaltfläche Tabellen verknüpfen zu betätigen.

Verbindungszeichenfolgen verwalten

Schließlich finden wir oben rechts noch eine Schaltfläche mit drei Punkten, mit der wir den Dialog zum Verwalten der Verbindungszeichenfolgen öffnen können.

Dieser sieht wie in Bild 3 aus und erlaubt das Eintragen der wesentlichen Merkmale einer SQL Server-Verbindung. Hier finden wir folgende Steuerelemente:

Verwalten von Verbindungszeichenfolgen

Bild 3: Verwalten von Verbindungszeichenfolgen

  • Bezeichnung: Selbst vergebene Bezeichnung für die Verbindungszeichenfolge
  • SQL Server: Adresse des SQL Servers, zum Beispiel Servername oder IP, gegebenenfalls unter Angabe des Instanznamens
  • Port: Port des SQL Servers, wenn abweichend vom Standardport 1433
  • Datenbank: Name der Datenbank. Dieser kann nach Festlegung des SQL Servers auch aus den vorhandenen Datenbanken ausgewählt werden.
  • Authentifizierung: Hier wählt man zwischen Windows-Authentifizierung und SQL Server-Authentifizierung.
  • Benutzername und Kennwort: Angabe der Zugangsdaten im Falle der SQL Server-Authentifizierung
  • Treiber: Auswahl des Treibers für die Verbindungszeichenfolge. Diese können wiederum über eine Tabelle im Add-In verwaltet werden.
  • Verbindungszeichenfolge: Stellt aus den gegebenen Informationen die Vorschau der Verbindungszeichenfolge zusammen.

Die Schaltflächen erlauben die folgenden Funktionen:

  • OK: Schließen des Formulars
  • Testen: Testaufruf der Verbindungszeichenfolge
  • Als Standard: Setzt die aktuelle Verbindungszeichenfolge als Standard
  • Neu: Legt eine neue, leere Verbindungszeichenfolge an
  • Kopieren als…: Kopiert die aktuelle Verbindungszeichenfolge als neue Zeichenfolge.
  • Löschen: Löscht die aktuelle Zeichenfolge.

Oben finden wir noch das Kombinationsfeld Schnellauswahl. Hier werden alle verfügbaren Verbindungszeichenfolgen zur Auswahl angeboten.

Das Formular ist an die Tabelle tblVerbindungszeichenfolgen gebunden (siehe Bild 4).

Die Tabelle tblVerbindungszeichenfolgen

Bild 4: Die Tabelle tblVerbindungszeichenfolgen

Die Treiber, die über das Feld TreiberID ausgewählt werden können, stammen aus der Tabelle tblTreiber (siehe Bild 5).

Die Tabelle tblTreiber

Bild 5: Die Tabelle tblTreiber

Automatische Übernahme der Verbindungszeichenfolge

Wenn wir den Dialog zum Verwalten der Verbindungszeichenfolge vom Formular zum Verknüpfen der Tabellen aus öffnen, wird dort direkt die Verbindungszeichenfolge angezeigt, die wir im aufrufenden Formular ausgewählt haben. Legen wir hier eine neue Verbindungszeichenfolge an oder wählen eine andere aus, wird diese nach dem Schließen des Dialogs automatisch im aufrufenden Formular selektiert.

Datenbank merkt sich die Verbindungszeichenfolge

Außerdem wollten wir noch eine Funktion hinzufügen, die dafür sorgt, dass beim Öffnen von amvTableLinker auf irgendeine Weise gespeichert wird, welche Verbindungszeichenfolge zuletzt zum Verknüpfen von Tabellen verwendet wurde. Damit wollen wir die Voraussetzung schaffen, dass beim nächsten Öffnen des amvTableLinkers in der gleichen Datenbank automatisch die richtige Verbindungszeichenfolge ausgewählt wird.

Dies haben wir realisiert, indem wir die Bezeichnung der Verbindungszeichenfolge in einer benutzerdefinierten Eigenschaft der Datenbank speichern.

Beim Öffnen von amvTableLinker prüfen wir, ob es diese Eigenschaft gibt und falls ja, wählen wir die entsprechende Verbindungszeichenfolge aus.

Programmieren der Formulare für amvTableLinker

Nun schauen wir uns an, wie wir die Formulare des Access-Add-Ins programmiert haben.

Wir beginnen mit dem Formular frmTabellenVerknuepfen, das in der Entwurfsansicht wie in Listing 1 aussieht.

Private Sub Form_Load()
     Dim db As DAO.Database
     Dim dbc As DAO.Database
     Dim prp As DAO.Property
     Dim rst As DAO.Recordset
     Dim strVerbindung As String
     Set db = CurrentDb
     Set dbc = CodeDb
     On Error Resume Next
     Set prp = db.Properties("Verbindung")
     On Error GoTo 0
     If Not prp Is Nothing Then
         strVerbindung = prp.Value
         Set rst = dbc.OpenRecordset("SELECT * FROM tblVerbindungszeichenfolgen WHERE Bezeichnung = ''" _
             & strVerbindung & "''", dbOpenDynaset)
         If Not rst.EOF Then
             Me.cboVerbindung = rst!VerbindungszeichenfolgeID
             Call cboVerbindung_AfterUpdate
         End If
     End If
End Sub

Listing 1: Diese Prozedur wird beim Laden des Formulars frmTabellenVerknuepfen ausgelöst.

Beim Laden des Formulars wird die Prozedur aus Bild 6 ausgelöst. Diese deklariert gleich zwei Variablen des Typs DAO.Database. Die erste namens db soll das Database-Objekt der Datenbank referenzieren, die das Add-In aufruft. Die zweite heißt dbc und soll das Database-Objekt der Add-In-Datenbank aufnehmen. Außerdem deklarieren wir Variablen für ein Property– und ein Recordset-Objekt.

Entwurf des Formulars frmTabellenVerknuepfen

Bild 6: Entwurf des Formulars frmTabellenVerknuepfen

Die beiden verschiedenen Database-Objekte füllen wir mit den Funktionen CurrentDb (für die aufrufende Datenbank) und CodeDb (für die Add-In-Datenbank).

Danach versuchen wir, die Eigenschaft Verbindung der aufrufenden Datenbank zu referenzieren.

In dieser haben wir gegebenenfalls zuvor die Bezeichnung der Verbindungszeichenfolge gespeichert, mit der wir die Tabellenverknüpfungen hergestellt haben. Dies erledigen wir bei deaktivierter Fehlerbehandlung, weil es auch sein kann, dass diese Eigenschaft noch gar nicht vorliegt – und das würde wiederum einen Fehler auslösen, den wir somit umgehen.

Ob das Zuweisen an die prp-Variable erfolgreich war, prüfen wir anschließend, indem es mit Is Nothing vergleichen. In diesem Fall ist prp vorhanden und wir lesen den Wert über die Eigenschaft Value in die Variable strVerbindung ein.

Damit können wir nun das Recordset rst füllen, und zwar mit einen Recordset auf Basis der Tabelle tblVerbindungszeichenfolgen. Für dieses legen wir fest, dass das Feld Bezeichnung mit dem Wert aus strVerbindung übereinstimmen soll. Das Recordset öffnen wir dabei mit der OpenRecordset-Methode der CodeDb-Datenbank aus dbc.

Ist das Recordset anschließend nicht leer, stellen wir das Kombinationsfeld cboVerbindung auf den Primärschlüsselwert des Recordsets ein und rufen die Prozedur cboVerbindung_AfterUpdate auf, die auch nach der manuellen Auswahl einer Verbindungszeichenfolge ausgelöst wird.

Anzeigen der Tabellen einer Verbindungszeichenfolge

Die oben erwähnte Prozedur cboVerbindung_AfterUpdate soll nach dem Selektieren eines Eintrags dieses Kombinationsfeldes alle Tabellen der Datenbank anzeigen, die in dieser Verbindungszeichenfolge referenziert wird.

Die Prozedur sehen wir in Listing 2. Sie verwendet ebenfalls zwei Database-Objektvariablen. Außerdem deklariert sie eine QueryDef-Variable und eine Recordset-Variable. Daneben benötigen wir eine String-Variable für die Verbindungszeichenfolge sowie eine Variant-Variable zum Durchlaufen der Listenfeld-Einträge.

Private Sub cboVerbindung_AfterUpdate()
     Dim db As DAO.Database
     Dim dbc As DAO.Database
     Dim qdf As DAO.QueryDef
     Dim rstTables As DAO.Recordset
     Dim strVerbindungszeichenfolge As String
     Dim lngErrorNumber As Long
     Dim strErrorDescription As String
     Dim var As Variant
     Set dbc = CodeDb
     Set db = CurrentDb
     If Len(strBenutzername) = 0 Then
         strBenutzername = Nz(dbc.OpenRecordset("SELECT Benutzername FROM tblVerbindungszeichenfolgen " _
         & "WHERE VerbindungszeichenfolgeID = " & Me!cboVerbindung).Fields(0), "")
     End If
     If Len(strKennwort) = 0 Then
         strKennwort = Nz(dbc.OpenRecordset("SELECT Kennwort FROM tblVerbindungszeichenfolgen " _
            & "WHERE VerbindungszeichenfolgeID = " & Me!cboVerbindung).Fields(0), "")
     End If
     If VerbindungTesten(Me!cboVerbindung, strVerbindungszeichenfolge, lngErrorNumber, strErrorDescription) = True Then
         Set qdf = db.CreateQueryDef("")
         With qdf
             .SQL = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE IN (''BASE TABLE'', ''VIEW'') " _
                 & "ORDER BY TABLE_TYPE, TABLE_NAME"
             .Connect = strVerbindungszeichenfolge
             .ReturnsRecords = True
         End With
         Set Me!lstTabellen.Recordset = qdf.OpenRecordset
         Set rstTables = db.OpenRecordset("SELECT Name FROM MSysObjects WHERE NOT Connect IS NULL", dbOpenDynaset)
         Do While Not rstTables.EOF
             For var = 0 To Me.lstTabellen.ListCount - 1
                 If Me!lstTabellen.ItemData(var) = rstTables!Name Then
                     Me.lstTabellen.Selected(var) = True
                 End If
             Next var
             rstTables.MoveNext
         Loop
     Else
         MsgBox "Keine gültige Verbindung." & vbCrLf & vbCrLf & strErrorDescription
     End If
End Sub

Listing 2: Anzeigen aller Tabellen der gewählten Verbindungszeichenfolge

Nach dem Füllen der Database-Variablen ermitteln wir die eventuell festgelegten Daten für die Anmeldung an die Datenbank und speichern diese in den Variablen strBenutzername und strKennwort, die als öffentliche Variablen im Modul mdlSQLServer deklariert sind. Hier würden wir normalerweise der Einfachheit halber DLookup-Funktionen nutzen. Aber damit würden wir immer auf die Datenbank zugreifen, die das Add-In aufgerufen hat. Daher müssen wir hier die OpenRecordset-Methode für das mit der Variablen dbc referenzierte Database-Objekt der Add-In-Datenbank verwenden.

Anschließend ruft die Prozedur die Funktion VerbindungTesten auf und übergibt den Primärschlüsselwert der zu untersuchenden Verbindungszeichenfolge sowie die beiden Variablen lngErrorNumber und strErrorDescription für eventuelle Rückmeldungen über Fehler und erwartet für den Parameter strVerbindungszeichenfolge die entsprechende Zeichenfolge zurück. Diese Funktion beschreiben wir weiter unten.

War der Aufruf erfolgreich, erstellt die Prozedur mit der CreateQueryDef-Methode ein neues, temporäres QueryDef-Objekt. Das erreichen wir, indem wir für den Parameter Name eine leere Zeichenkette übergeben.

Dieser weisen wir nun über die Eigenschaft SQL eine SQL-Anweisung zu, die alle Tabellennamen aus der Systemtabelle Information_Schema.Table holt, deren Typ BASE TABLE oder VIEW lautet. Als Verbindungszeichenfolge geben wir für die Eigenschaft Connect den Wert aus strVerbindungszeichenfolge an. Schließlich stellen wir die Eigenschaft ReturnsRecords auf True ein, damit die Abfrage Datensätze zurückliefert (im Gegensatz zu einer Aktionsabfrage).

Das mit der OpenRecordset-Methode auf Basis des QueryDef-Objekts aus der Variablen qdf geöffnete Recordset weisen wir direkt der gleichnamigen Eigenschaft des Listenfeldes lstTabellen zu.

Außerdem erstellen wir ein Recordset namens rstTables, das wir mit Datensätzen der Systemtabelle MSysObjects der aufrufenden Access-Datenbank füllen. Diese beschränken wir auf alle Datensätze, deren Eigenschaft Connect nicht leer ist – was in der Regel die per ODBC eingebundenen Tabellen eindeutig identifiziert.

Dieses Recordset durchlaufen wir in einer Do While-Schleife. Innerhalb der Schleife durchlaufen wir in einer For…Each-Schleife alle Elemente des Listenfeldes lstTabellen. Dabei vergleichen wir jeweils den Eintrag des Listenfeldes mit dem Namen der aktuellen Tabelle aus dem Recordset.

Sind beide gleich, bedeutet dies, dass die Tabelle aus dem SQL Server bereits in Form einer Tabellenverknüpfung in der aufrufenden Datenbank hinterlegt ist. In diesem Fall soll dieser Eintrag im Listenfeld selektiert werden, was wir durch Einstellen der Eigenschaft Selected für das Element var auf den Wert True erledigen.

Auf diese Weise füllen wir das Listenfeld lstTabellen und markieren gleichzeitig alle bereits verknüpften Tabellen. Dies gelingt übrigens nur, wenn der Name der Tabelle im SQL Server mit dem Namen der Verknüpfung übereinstimmt.

Testen der Verbindung

Damit wir Tabellenverknüpfungen herstellen können, benötigen wir eine funktionsfähige Verbindungszeichenfolge. Diese prüfen wir zuvor mit der Funktion VerbindungTesten, die wir in Listing 3 finden. Sie nimmt den Primärschlüsselwert des Eintrags der Tabelle tblVerbindungszeichenfolgen für die zu untersuchende Verbindungszeichenfolge entgegen. Außerdem enthält sie einen zweiten Parameter, mit dem die ermittelte Verbindungszeichenfolge zurückgegeben werden kann. Daneben hat die Funktion den Datentyp Boolean und liefert mit dem Rückgabewert die Information, ob die Verbindungszeichenfolge erfolgreich getestet werden konnte.

Public Function VerbindungTesten(lngVerbindungszeichenfolgeID As Long, _
         Optional strVerbindungszeichenfolge As String, Optional lngErrorNumber As Long, _
         Optional strErrorDescription As String) As Boolean
     Dim dbc As dao.Database
     Dim bolTrustedConnection As Boolean
     Dim bolVerbindungHergestellt As Boolean
     Set dbc = CodeDb
     bolTrustedConnection = dbc.OpenRecordset("SELECT TrustedConnection FROM tblVerbindungszeichenfolgen " _
         & "WHERE VerbindungszeichenfolgeID = " & lngVerbindungszeichenfolgeID).Fields(0)
     If (Len(strBenutzername) * Len(strKennwort) = 0) And Not bolTrustedConnection Then
         If LogindatenErmitteln(lngVerbindungszeichenfolgeID) = False Then
             Exit Function
         End If
     End If
     strVerbindungszeichenfolge = VerbindungszeichenfolgeNachID(lngVerbindungszeichenfolgeID)
     On Error Resume Next
     bolVerbindungHergestellt = VerbindungHerstellen(strVerbindungszeichenfolge, lngErrorNumber, strErrorDescription)
     If bolVerbindungHergestellt = False Then
         VerbindungTesten = False
         Exit Function
     End If
     VerbindungTesten = True
End Function

Listing 3: Testen der Verbindung für die Verbindungszeichenfolge

Die Prozedur ermittelt auf Basis des Feldes TrustedConnection, ob es sich um eine Verbindungszeichenfolge für den Zugriff mit Windows-Authentifizierung oder mit SQL Server-Authentifizierung handelt.

Wenn Benutzername und/oder Kennwort leer sind und die SQL Server-Authentifizierung verwendet werden soll, benötigen wir vermutlich noch die Anmeldedaten, wozu die Funktion LogindatenErmitteln mit der Verbindungszeichenfolge als Parameter aufgerufen wird (mehr dazu weiter unten). Liefert diese Funktion wiederum den Wert False zurück, wird der Test erfolglos abgebrochen.

Anderenfalls geht es mit den Daten, die durch diese Funktion in die Variablen strBenutzername und strKennwort geschrieben wurden, weiter.

Die Hilfsfunktion VerbindungszeichenfolgeNachID (siehe unten) erhält den Primärschlüsselwert der Verbindungszeichenfolge und soll den entsprechenden String ermitteln. Dieser landet anschließend in der Variablen strVerbindungszeichenfolge.

Damit rufen wir bei deaktivierter Fehlerbehandlung eine weitere Funktion namens VerbindungHerstellen auf und übergeben dieser die Verbindungszeichenfolge.

Das Ergebnis landet in der Variablen bolVerbindungHergestellt.

Enthält diese nun den Wert False, wird auch False als Ergebnis der Funktion VerbindungTesten zurückgegeben und die Funktion mit Exit Function verlassen. Anderenfalls wird der Wert True als Ergebnis von VerbindungTesten zurückgeliefert.

Ermitteln der Login-Daten per Formular

Die Funktion LogindatenErmitteln öffnet ein Formular, das in der Entwurfsansicht wie in Bild 7 aussieht. Sie öffnet das Formular als modalen Dialog und übergibt dieser die ID der zu verwendenden Verbindungszeichenfolgt als Öffnungsargument.

Entwurf des Formulars frmLogin

Bild 7: Entwurf des Formulars frmLogin

Nachdem das Formular mit der OK-Schaltfläche ausgeblendet wurde, läuft die aufrufende Prozedur weiter und liest den Benutzernamen und das Kennwort aus den dafür vorgesehenen Textfeldern des Formulars in die Variablen strBenutzername und strKennwort ein. Dann schließt sie das Formular und stellt den Rückgabewert der Funktion auf True ein:

Public Function LogindatenErmitteln( _
         lngVerbindungszeichenfolgeID) As Boolean
     DoCmd.OpenForm "frmLogin", WindowMode:=acDialog, _
         OpenArgs:=lngVerbindungszeichenfolgeID
     If IstFormularGeoeffnet("frmLogin") Then
         strBenutzername = Forms!frmLogin!txtBenutzername
         strKennwort = Forms!frmLogin!txtKennwort
         DoCmd.Close acForm, "frmLogin"
         LogindatenErmitteln = True
     End If
End Function

Das Formular löst beim Öffnen die Prozedur aus Listing 4 aus. Diese liest aus dem Öffnungsargument die zu verwendende Verbindungszeichenfolge ein und speichert sie in lngVerbindungszeichenfolgeID. Hat diese den Wert 0, verwendet die Prozedur die Standardverbindungszeichenfolge, die mit der Funktion StandardverbindungszeichenfolgeErmitteln eingelesen wird.

Private Sub Form_Open(Cancel As Integer)
     Dim dbc As DAO.Database
     Dim strVerbindungszeichenfolge As String
     Set dbc = CodeDb
     lngVerbindungszeichenfolgeID = Nz(Me.OpenArgs)
     If lngVerbindungszeichenfolgeID = 0 Then
         lngVerbindungszeichenfolgeID = StandardverbindungszeichenfolgeID
     End If
     Me!txtBenutzername = Nz(dbc.OpenRecordset("SELECT Benutzername FROM tblVerbindungszeichenfolgen " _
         & "WHERE VerbindungszeichenfolgeID = " & lngVerbindungszeichenfolgeID).Fields(0), strBenutzername)
     Me!txtKennwort = Nz(dbc.OpenRecordset("SELECT Kennwort FROM tblVerbindungszeichenfolgen " _
         & "WHERE VerbindungszeichenfolgeID = " & lngVerbindungszeichenfolgeID).Fields(0), strKennwort)
End Sub

Listing 4: Einstellen des Loginformulars beim Öffnen

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