Performanter Webzugriff auf MySQL-Datenbanken

Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.

Wer einen Webserver sein Eigen nennt oder anderweitig Gelegenheit zum Ablegen von Daten in einer MySQL-Datenbank hat, kann dies für verschiedene Zwecke nutzen: Primär sollen Datenbanken auf Webservern natürlich Inhalte für Internetseiten liefern, aber Sie können diese natürlich auch einfach als zentrale Datenbasis verwenden und von überall auf diese zugreifen. Wenn dies auch noch in akzeptabler Zeit gelingen soll, müssen Sie jedoch einige Regeln beachten.

Wenn Sie direkt auf eine Datenbank auf einem Webserver zugreifen können, ergeben sich eine ganze Menge Möglichkeiten.

Sie können nicht nur, wie oben beschrieben, Daten zentral speichern und dann von überall darauf zugreifen, sondern natürlich auch mehreren Personen gleichzeitig Zugriff auf die Daten verschaffen.

Außerdem sparen Sie sich damit unter Umständen die aufwendige Programmierung von Web-Backends für die Datenbanken Ihrer Webseiten: Sie können die Daten nämlich, eine geeignete Verbindung und Access-Anwendung vorausgesetzt, ganz einfach per Formular ändern oder per Bericht anzeigen lassen.

Dies ändert natürlich nichts an der Tatsache, dass Sie für die Besucher der Webseite ein HTML-Frontend bauen müssen, aber in vielen Fällen stellt die Administration der auf der Webseite dargestellten Daten eine wesentlich höhere Herausforderung als die eigentliche Webseite dar.

Was brauchen Sie, um vom vorliegenden Beitrag profitieren zu können Da wäre als Erstes eine MySQL-Datenbank irgendwo auf einem Webserver und zweitens die Möglichkeit, per ODBC darauf zuzugreifen – sei es direkt oder über den Umweg eines Tunnels, wie im Beitrag Access und MySQL (Shortlink 240) beschrieben.

Dies zieht nach sich, dass Sie auf Ihrem lokalen Rechner einen ODBC-Connector für die MySQL-Datenbank installieren müssen. Die aktuellste Version finden Sie unter dem Link http://dev.mysql.com/downloads/connector/odbc/5.1.html. Als Nächstes müssen Sie die Verbindungsparameter für den Aufbau einer Verbindung zum MySQL-Server auf dem Webserver ermitteln. Eine gute Anlaufstelle finden Sie unter http://www.connectionstrings.com/.

Der Standardweg

Normalerweise würden Sie die Tabellen der MySQL-Datenbank mit dem Access-Frontend per ODBC verknüpfen. Dies funktioniert insbesondere deshalb sehr gut, weil Sie die Tabellen fast genau wie in der lokalen Access-Datenbank enthaltene Tabellen behandeln können – sie lassen sich in Abfragen zusammenführen, an Formulare, Berichte und die enthaltenen Steuerelemente binden und auch der Zugriff per ADO oder DAO geschieht problemlos.

Dummerweise gibt es ein Problem: Wenn die Datenmenge wächst oder Abfragen über mehrere Tabellen abgefragt werden sollen, gerät etwa die Anzeige von Daten in einem Formular mitunter zum Geduldsspiel.

Welche Alternativen gibt es hierzu Wenn es um das reine Anzeigen von Daten geht, diese also nicht bearbeitet werden sollen, können Sie PassThrough-Abfragen verwenden.

Diese unterscheiden sich dadurch von herkömmlichen Abfragen, dass sie erstens im nativen SQL-Dialekt des DBMS formuliert sein müssen, die Angabe einer entsprechenden ODBC-Verbindung erfordern und außerdem einen entscheidenden Nachteil haben: sie lassen keine Veränderungen an den gelieferten Daten zu.

Und damit kommen wir zur Methode dieses Beitrags: Der Zugriff erfolgt ausschließlich über ADO-Recordsets und unterscheidet sich somit wesentlich von den üblicherweise verwendeten Möglichkeiten zum Binden von Formularen, Berichten und Steuerelementen an Datenherkünfte wie Tabellen oder Abfragen.

Wie aber können wir ein Formular, einen Bericht oder auch ein Kombinationsfeld mit Daten füllen, auf die wir nur per ADO zugreifen ADO wird doch normalerweise ausschließlich in VBA-Prozeduren verwendet

Per VBA, ADODB und ODBC auf eine Tabelle zugreifen

Beginnen wir gleich dort, nämlich beim Einlesen von Daten via VBA, DAO und ODBC. Kern dieser Vorgehensweise sind wie üblich ein Connection– und ein Recordset-Objekt, die allerdings etwas anders als sonst üblich gefüllt werden. Als Beispieltabellen verwenden wir vier einfache Tabellen, deren Beziehungen wie in Bild 1 aufgebaut sind. Um die wichtigsten Fälle abzudecken, haben wir eine 1:n- und eine m:n-Beziehung eingebaut.

pic001.png

Bild 1: Datenmodell der Beispieldatenbank

Diese haben wir in Access erstellt und mit den im Beitrag Von Access nach MySQL (Shortlink ****) beschriebenen Techniken in eine auf einem Webserver liegende MySQL-Datenbank migriert. Wenn wir mit ADO arbeiten, was in diesem Fall die schnellste Variante ist, benötigen wir zunächst einmal ein Connection-Objekt. Da eine Anwendung meist über mehrere Formulare verfügt und diese alle schnell mit Daten gefüllt werden sollen, machen wir das Connection-Objekt über eine globale Funktion verfügbar. Die folgenden Codezeilen liegen alle in einem Standardmodul namens mdlMySQL. Den Start macht die Deklaration einer Connection-Variablen zum Speichern eines Verweises auf die aktuelle Verbindung:

Private m_Connection As ADODB.Connection

Damit wir den Connectionstring nicht an verschiedenen Stellen ändern müssen, wenn dies einmal notwendig ist, schreiben wir ihn in eine Konstante:

Public Const strConnection As String = "Driver={MySQL ODBC 5.1 Driver};Server=<IP des Webservers>;Database=<Datenbankname>;User=<Benutzername>;Password=<Kennwort>;Option=3;"

Die folgende Funktion liefert schließlich ein Connection-Objekt. Dabei prüft sie, ob schon ein Connection-Objekt vorliegt, und gibt dieses zurück – falls nicht, erzeugt sie eine neue Verbindung:

Public Function GetConnection() As _
    ADODB.Connection
    If m_Connection Is Nothing Then
        Set m_Connection = New ADODB.Connection
        m_Connection.Open strConnection
    End If
    Set GetConnection = m_Connection
End Function

Beachten Sie bitte, dass es einen serverseitigen Timeout gibt. Gegebenenfalls ist die Connection nach einer halben Tasse Kaffee nicht mehr verfügbar. Hier müssen Sie entweder serverseitig den Timeout erhöhen oder anderweitige Maßnahmen treffen.

Recordset erzeugen

Wie oben erwähnt, möchten wir ausschließlich auf der Basis von Recordsets arbeiten. Da bietet es sich an, genau wie bei den Connection-Objekten eine Funktion zu bauen, welche die gewünschten Recordsets zurückliefert. Die Funktion GetRecordset erwartet zwei Parameter:

  • objConnection: Verweis auf eine geöffnete Verbindung, idealerweise über die Funktion GetConnection zu beziehen
  • strSQL: SQL-String der Datenherkunft des Recordsets, gegebenenfalls in der Syntax des SQL-Servers; auch Stored Procedures oder View möglich

Die Funktion stellt einige Parameter für das zu erzeugende Recordset-Objekt ein, öffnet dieses und gibt einen Verweis darauf als Funktionswert zurück:

Public Function GetRecordset( _
    objConnection As ADODB.Connection, _
    strSQL As String) As ADODB.Recordset
    Dim rst As ADODB.Recordset
    Set rst = New ADODB.Recordset
    With rst
        .ActiveConnection = objConnection
        .CursorLocation = adUseClient
        .CursorType = adOpenDynamic
        .LockType = adLockBatchOptimistic
        .Source = strSQL
        .Open , , , , adCmdText
        Set GetRecordset = rst
    End With
End Function

Formular mit Daten füllen

Kommen wir nun zum eigentlichen Thema: dem Füllen eines Formulars mit Daten einer MySQL-Datenbank auf einem Webserver. Den größten Teil der Arbeit haben wir bereits erledigt, fehlt nur noch das passende Formular. Dieses soll im ersten Beispiel die Daten der Tabelle tblKunden als einzelne Datensätze anzeigen. Die Beispieldatenbank enthält noch die für das Erstellen der MySQL-Datenbank verwendeten Tabellen inklusive Daten, sodass Sie diese zunächst zum Füllen des Formulars mit den benötigten Feldern verwenden können. Erstellen Sie dazu ein neues, leeres Formular, stellen Sie die Eigenschaft Datenherkunft auf die Tabelle tblKunden ein und ziehen Sie alle Felder der Tabelle aus der Feldliste in den Entwurf des Formulars (siehe Bild 2). Leeren Sie nun unbedingt die Eigenschaft Datenherkunft wieder – schließlich möchten wir nicht die Daten der lokalen Tabelle anzeigen, sondern die vom Webserver. Damit dies gelingt, legen Sie nun eine Ereignisprozedur für die Ereigniseigenschaft Beim Laden des Formulars an. Füllen Sie diese wie folgt:

pic002.png

Bild 2: Entwurf des ersten Beispielformulars

Private Sub Form_Load()
    Set Me.Recordset = GetRecordset( _
    GetConnection, _
    "SELECT * FROM tblKunden")
End Sub

Wenn Sie nun in die Formularansicht wechseln, erscheinen die gewünschten Datensätze. Sie können diese ändern und löschen und auch neue Datensätze anlegen.

1:n-Beziehung abbilden

1:n-Beziehungen lassen sich auf zwei Arten abbilden, und zwar aus der Sicht jeder einzelnen der beiden beteiligten Tabellen.

Im ersten Beispiel wollen wir einen Kunden zu einer Bestellung auswählen, was mit einem Kombinationsfeld geschieht. Im zweiten Beispiel sollen alle Bestellungen zu einem Kunden aufgelistet werden.

Kombinationsfelder füllen

Der interessante Teil beim Abbilden einer 1:n-Beziehung aus Sicht des Bestellungsdatensatzes ist das Kombinationsfeld zum Auswählen des Kunden.

Das Formular zu diesem Beispiel heißt frmBestellung und zeigt alle Felder der Tabelle tblBestellungen an. Die Felder fügen Sie am einfachsten wie oben beschrieben hinzu, indem Sie zunächst die lokale Tabelle tblBestellungen als Datenherkunft einstellen, die Felder ins Formular ziehen und die Datenherkunft wieder leeren. Danach legen Sie die folgende Prozedur für das Ereignis Beim Laden an:

Private Sub Form_Load()
    Set Me.Recordset = GetRecordset( _
    GetConnection, _
    "SELECT * FROM tblBestellungen")
End Sub

Danach funktioniert das Formular gleich wie gewünscht – es zeigt sogar die Daten aus der Tabelle tblKunden im Kombinationsfeld zur Auswahl des Kunden an (siehe Bild 3).

pic003.png

Bild 3: Das Kombinationsfeld ist bereits gefüllt, aber aus der falschen Quelle.

Allerdings stammen diese Daten natürlich nicht vom Webserver, sondern aus der lokalen Tabelle. Die notwendige Datensatzherkunft des Formulars wurde beim Hinzufügen der Felder auf Basis der lokalen Tabelle tblBestellungen eingetragen.

Wir wollen aber alle Daten von der Datenbank auf dem Webserver beziehen. Wechseln Sie also in die Entwurfsansicht des Formulars, markieren Sie das Kombinationsfeld zur Auswahl des Kunden und leeren Sie dessen Eigenschaft Datensatzherkunft.

Beim nächsten Wechseln in die Formularansicht ist das Kombinationsfeld leer, was auch logisch ist: Es enthält zwar den Wert des Feldes KundeID der dem Formular als Recordset zugewiesenen Tabelle tblBestellungen, diese wird jedoch nicht angezeigt, weil die Einstellungen der Eigenschaften Spaltenanzahl und Spaltenbreiten dafür ausgelegt sind, den Inhalt des zweiten Felds der Datensatzherkunft des Kombinationsfelds anzuzeigen – und da diese leer ist, zeigt das Formular eine leere Zeichenkette an. Da es nicht leer ist, können Sie durch das Einstellen der Eigenschaften Spaltenanzahl und Spaltenbreiten auf 1 und 3cm nachweisen.

Damit das Kombinationsfeld die auf dem Webserver gespeicherten Kundennamen zur Auswahl anbietet, müssen wir auch dessen Recordset-Eigenschaft mit einem Verweis auf das entsprechend Recordset füllen. Dazu erweitern Sie die Beim Laden-Ereignisprozedur von oben um die folgende Zeile:

Set Me!KundeID.Recordset = _
GetRecordset(GetConnection, _
"SELECT KundeID, Nachname " _
    & "FROM tblKunden ORDER BY Nachname")

Dies zeigt nun die gewünschten Kunden an. Statt des Nachnamens sollen die Kundendaten in einem weiteren Schritt in der Form Nachname, Vorname angezeigt werden. Normalerweise würden wir die SQL-Abfrage dazu wie folgt ändern:

SELECT KundeID, Nachname & '', '' & Vorname AS Kunde FROM tblKunden ORDER BY Nachname

Dies funktioniert jedoch nicht: Das Kombinationsfeld zeigt zwar die richtige Anzahl Datensätze an, allerdings ohne Angabe des Kundennamens.

Der Grund ist einfach: Wenn wir Abfragen wie hier per ADO direkt an den SQL-Server absetzen, müssen diese im SQL-Dialekt des jeweiligen SQL-Servers, hier MySQL, formuliert werden. Und MySQL verwendet zum Konkatenieren von Feldern die CONCAT-Funktion. Die SQL-Abfrage muss also so aussehen:

SELECT KundeID, CONCAT(Nachname, '', '', Vorname) AS Kunde FROM tblKunden ORDER BY Nachname

Nun zeigt das Kombinationfeld die gewünschten Ausdrücke an und erlaubt auch deren änderung. Alternativ können Sie auch eine PassThrough-Abfrage als Datensatzherkunft verwenden.

1:n-Beziehung mit Unterformular

Die umgekehrte Ansicht soll alle Bestellungen zu einem Kunden anzeigen. Dazu benötigen wir ein Listen-Steuerelement wie ein Listenfeld oder ein Unterformular in der Datenblatt- oder Endlosansicht. In diesem Fall verwenden wir ein Unterformular in der Datenblattansicht. Das Hauptformular soll alle Kunden-Daten anzeigen, weshalb Sie das Formular frmKunden aus dem ersten Beispiel weiterverwenden können.

Das Unterformular zum Anzeigen der Bestellungen soll sfmKunden heißen und erhält zunächst die Tabelle tblBestellungen als Datenherkunft, damit Sie die gebundenen Felder schnell zum Entwurf hinzufügen können. Danach leeren Sie die Datenherkunft, schließen das Formular und fügen es dem Formular frmKunden als Unterformular hinzu – am einfachsten gelingt dies, indem Sie frmKunden im Entwurf öffnen und das Formular sfmKunden aus dem Datenbankfenster in den Detailbereich ziehen. Das Ergebnis sieht dann wie in Bild 4 aus. ändern Sie den Steuerelementtyp des Felds KundeID in Textfeld – es dient später nur der Prüfung, ob das Feld den richtigen Standardwert aufweist, und kann anschließend entfernt werden.

pic004.png

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

Testzugang

eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar