{"id":55000702,"date":"2010-02-01T00:00:00","date_gmt":"2020-05-22T22:10:40","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=702"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Performanter_Webzugriff_auf_MySQLDatenbanken","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/","title":{"rendered":"Performanter Webzugriff auf MySQL-Datenbanken"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg05.met.vgwort.de\/na\/1e33a7deee0e49f4af3c5e6034795928\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Wer einen Webserver sein Eigen nennt oder anderweitig Gelegenheit zum Ablegen von Daten in einer MySQL-Datenbank hat, kann dies f&uuml;r verschiedene Zwecke nutzen: Prim&auml;r sollen Datenbanken auf Webservern nat&uuml;rlich Inhalte f&uuml;r Internetseiten liefern, aber Sie k&ouml;nnen diese nat&uuml;rlich auch einfach als zentrale Datenbasis verwenden und von &uuml;berall auf diese zugreifen. Wenn dies auch noch in akzeptabler Zeit gelingen soll, m&uuml;ssen Sie jedoch einige Regeln beachten.<\/b><\/p>\n<p>Wenn Sie direkt auf eine Datenbank auf einem Webserver zugreifen k&ouml;nnen, ergeben sich eine ganze Menge M&ouml;glichkeiten.<\/p>\n<p>Sie k&ouml;nnen nicht nur, wie oben beschrieben, Daten zentral speichern und dann von &uuml;berall darauf zugreifen, sondern nat&uuml;rlich auch mehreren Personen gleichzeitig Zugriff auf die Daten verschaffen.<\/p>\n<p>Au&szlig;erdem sparen Sie sich damit unter Umst&auml;nden die aufwendige Programmierung von Web-Backends f&uuml;r die Datenbanken Ihrer Webseiten: Sie k&ouml;nnen die Daten n&auml;mlich, eine geeignete Verbindung und Access-Anwendung vorausgesetzt, ganz einfach per Formular &auml;ndern oder per Bericht anzeigen lassen.<\/p>\n<p>Dies &auml;ndert nat&uuml;rlich nichts an der Tatsache, dass Sie f&uuml;r die Besucher der Webseite ein HTML-Frontend bauen m&uuml;ssen, aber in vielen F&auml;llen stellt die Administration der auf der Webseite dargestellten Daten eine wesentlich h&ouml;here Herausforderung als die eigentliche Webseite dar.<\/p>\n<p>Was brauchen Sie, um vom vorliegenden Beitrag profitieren zu k&ouml;nnen Da w&auml;re als Erstes eine MySQL-Datenbank irgendwo auf einem Webserver und zweitens die M&ouml;glichkeit, per ODBC darauf zuzugreifen &#8211; sei es direkt oder &uuml;ber den Umweg eines Tunnels, wie im Beitrag <b>Access und MySQL <\/b>(Shortlink 240) beschrieben.<\/p>\n<p>Dies zieht nach sich, dass Sie auf Ihrem lokalen Rechner einen ODBC-Connector f&uuml;r die MySQL-Datenbank installieren m&uuml;ssen. Die aktuellste Version finden Sie unter dem Link <b>http:\/\/dev.mysql.com\/downloads\/connector\/odbc\/5.1.html<\/b>. Als N&auml;chstes m&uuml;ssen Sie die Verbindungsparameter f&uuml;r den Aufbau einer Verbindung zum MySQL-Server auf dem Webserver ermitteln. Eine gute Anlaufstelle finden Sie unter <b>http:\/\/www.connectionstrings.com\/<\/b>.<\/p>\n<p><b>Der Standardweg<\/b><\/p>\n<p>Normalerweise w&uuml;rden Sie die Tabellen der MySQL-Datenbank mit dem Access-Frontend per ODBC verkn&uuml;pfen. Dies funktioniert insbesondere deshalb sehr gut, weil Sie die Tabellen fast genau wie in der lokalen Access-Datenbank enthaltene Tabellen behandeln k&ouml;nnen &#8211; sie lassen sich in Abfragen zusammenf&uuml;hren, an Formulare, Berichte und die enthaltenen Steuerelemente binden und auch der Zugriff per ADO oder DAO geschieht problemlos.<\/p>\n<p>Dummerweise gibt es ein Problem: Wenn die Datenmenge w&auml;chst oder Abfragen &uuml;ber mehrere Tabellen abgefragt werden sollen, ger&auml;t etwa die Anzeige von Daten in einem Formular mitunter zum Geduldsspiel.<\/p>\n<p>Welche Alternativen gibt es hierzu Wenn es um das reine Anzeigen von Daten geht, diese also nicht bearbeitet werden sollen, k&ouml;nnen Sie <b>PassThrough<\/b>-Abfragen verwenden.<\/p>\n<p>Diese unterscheiden sich dadurch von herk&ouml;mmlichen Abfragen, dass sie erstens im nativen SQL-Dialekt des DBMS formuliert sein m&uuml;ssen, die Angabe einer entsprechenden ODBC-Verbindung erfordern und au&szlig;erdem einen entscheidenden Nachteil haben: sie lassen keine Ver&auml;nderungen an den gelieferten Daten zu.<\/p>\n<p>Und damit kommen wir zur Methode dieses Beitrags: Der Zugriff erfolgt ausschlie&szlig;lich &uuml;ber ADO-Recordsets und unterscheidet sich somit wesentlich von den &uuml;blicherweise verwendeten M&ouml;glichkeiten zum Binden von Formularen, Berichten und Steuerelementen an Datenherk&uuml;nfte wie Tabellen oder Abfragen. <\/p>\n<p>Wie aber k&ouml;nnen wir ein Formular, einen Bericht oder auch ein Kombinationsfeld mit Daten f&uuml;llen, auf die wir nur per ADO zugreifen ADO wird doch normalerweise ausschlie&szlig;lich in VBA-Prozeduren verwendet<\/p>\n<p><b>Per VBA, ADODB und ODBC auf eine Tabelle zugreifen<\/b><\/p>\n<p>Beginnen wir gleich dort, n&auml;mlich beim Einlesen von Daten via VBA, DAO und ODBC. Kern dieser Vorgehensweise sind wie &uuml;blich ein <b>Connection<\/b>&#8211; und ein <b>Recordset<\/b>-Objekt, die allerdings etwas anders als sonst &uuml;blich gef&uuml;llt werden. Als Beispieltabellen verwenden wir vier einfache Tabellen, deren Beziehungen wie in Bild 1 aufgebaut sind. Um die wichtigsten F&auml;lle abzudecken, haben wir eine 1:n- und eine m:n-Beziehung eingebaut.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_01\/MySQLDirekt-web-images\/pic001_opt.jpeg\" alt=\"pic001.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1: Datenmodell der Beispieldatenbank<\/span><\/b><\/p>\n<p>Diese haben wir in Access erstellt und mit den im Beitrag <b>Von Access nach MySQL <\/b>(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&ouml;tigen wir zun&auml;chst einmal ein <b>Connection<\/b>-Objekt. Da eine Anwendung meist &uuml;ber mehrere Formulare verf&uuml;gt und diese alle schnell mit Daten gef&uuml;llt werden sollen, machen wir das <b>Connection<\/b>-Objekt &uuml;ber eine globale Funktion verf&uuml;gbar. Die folgenden Codezeilen liegen alle in einem Standardmodul namens <b>mdlMySQL<\/b>. Den Start macht die Deklaration einer <b>Connection<\/b>-Variablen zum Speichern eines Verweises auf die aktuelle Verbindung:<\/p>\n<pre>Private m_Connection As ADODB.Connection<\/pre>\n<p>Damit wir den Connectionstring nicht an verschiedenen Stellen &auml;ndern m&uuml;ssen, wenn dies einmal notwendig ist, schreiben wir ihn in eine Konstante:<\/p>\n<pre>Public Const strConnection As String = &quot;Driver={MySQL ODBC 5.1 Driver};Server=&lt;IP des Webservers&gt;;Database=&lt;Datenbankname&gt;;User=&lt;Benutzername&gt;;Password=&lt;Kennwort&gt;;Option=3;&quot;<\/pre>\n<p>Die folgende Funktion liefert schlie&szlig;lich ein <b>Connection<\/b>-Objekt. Dabei pr&uuml;ft sie, ob schon ein Connection-Objekt vorliegt, und gibt dieses zur&uuml;ck &#8211; falls nicht, erzeugt sie eine neue Verbindung:<\/p>\n<pre>Public Function GetConnection() As _\r\n    ADODB.Connection\r\n    If m_Connection Is Nothing Then\r\n        Set m_Connection = New ADODB.Connection\r\n        m_Connection.Open strConnection\r\n    End If\r\n    Set GetConnection = m_Connection\r\nEnd Function<\/pre>\n<p>Beachten Sie bitte, dass es einen serverseitigen Timeout gibt. Gegebenenfalls ist die Connection nach einer halben Tasse Kaffee nicht mehr verf&uuml;gbar. Hier m&uuml;ssen Sie entweder serverseitig den Timeout erh&ouml;hen oder anderweitige Ma&szlig;nahmen treffen.<\/p>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Recordset erzeugen<\/p>\n<p>Wie oben erw&auml;hnt, m&ouml;chten wir ausschlie&szlig;lich auf der Basis von Recordsets arbeiten. Da bietet es sich an, genau wie bei den <b>Connection<\/b>-Objekten eine Funktion zu bauen, welche die gew&uuml;nschten Recordsets zur&uuml;ckliefert. Die Funktion <b>GetRecordset <\/b>erwartet zwei Parameter:<\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>objConnection<\/b>: Verweis auf eine ge&ouml;ffnete Verbindung, idealerweise &uuml;ber die Funktion <b>GetConnection<\/b> zu beziehen<\/li>\n<li class=\"aufz-hlung\"><b>strSQL<\/b>: SQL-String der Datenherkunft des Recordsets, gegebenenfalls in der Syntax des SQL-Servers; auch Stored Procedures oder View m&ouml;glich<\/li>\n<\/ul>\n<p>Die Funktion stellt einige Parameter f&uuml;r das zu erzeugende <b>Recordset<\/b>-Objekt ein, &ouml;ffnet dieses und gibt einen Verweis darauf als Funktionswert zur&uuml;ck:<\/p>\n<pre>Public Function GetRecordset( _\r\n    objConnection As ADODB.Connection, _\r\n    strSQL As String) As ADODB.Recordset\r\n    Dim rst As ADODB.Recordset\r\n    Set rst = New ADODB.Recordset\r\n    With rst\r\n        .ActiveConnection = objConnection\r\n        .CursorLocation = adUseClient\r\n        .CursorType = adOpenDynamic\r\n        .LockType = adLockBatchOptimistic\r\n        .Source = strSQL\r\n        .Open , , , , adCmdText\r\n        Set GetRecordset = rst\r\n    End With\r\nEnd Function<\/pre>\n<p><b>Formular mit Daten f&uuml;llen<\/b><\/p>\n<p>Kommen wir nun zum eigentlichen Thema: dem F&uuml;llen eines Formulars mit Daten einer MySQL-Datenbank auf einem Webserver. Den gr&ouml;&szlig;ten Teil der Arbeit haben wir bereits erledigt, fehlt nur noch das passende Formular. Dieses soll im ersten Beispiel die Daten der Tabelle <b>tblKunden <\/b>als einzelne Datens&auml;tze anzeigen. Die Beispieldatenbank enth&auml;lt noch die f&uuml;r das Erstellen der MySQL-Datenbank verwendeten Tabellen inklusive Daten, sodass Sie diese zun&auml;chst zum F&uuml;llen des Formulars mit den ben&ouml;tigten Feldern verwenden k&ouml;nnen. Erstellen Sie dazu ein neues, leeres Formular, stellen Sie die Eigenschaft <b>Datenherkunft <\/b>auf die Tabelle <b>tblKunden <\/b>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 <b>Datenherkunft <\/b>wieder &#8211; schlie&szlig;lich m&ouml;chten wir nicht die Daten der lokalen Tabelle anzeigen, sondern die vom Webserver. Damit dies gelingt, legen Sie nun eine Ereignisprozedur f&uuml;r die Ereigniseigenschaft <b>Beim Laden <\/b>des Formulars an. F&uuml;llen Sie diese wie folgt:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_01\/MySQLDirekt-web-images\/pic002_opt.jpeg\" alt=\"pic002.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2: Entwurf des ersten Beispielformulars<\/span><\/b><\/p>\n<pre>Private Sub Form_Load()\r\n    Set Me.Recordset = GetRecordset( _\r\n    GetConnection, _\r\n    &quot;SELECT * FROM tblKunden&quot;)\r\nEnd Sub<\/pre>\n<p>Wenn Sie nun in die Formularansicht wechseln, erscheinen die gew&uuml;nschten Datens&auml;tze. Sie k&ouml;nnen diese &auml;ndern und l&ouml;schen und auch neue Datens&auml;tze anlegen.<\/p>\n<p><b>1:n-Beziehung abbilden<\/b><\/p>\n<p>1:n-Beziehungen lassen sich auf zwei Arten abbilden, und zwar aus der Sicht jeder einzelnen der beiden beteiligten Tabellen.<\/p>\n<p>Im ersten Beispiel wollen wir einen Kunden zu einer Bestellung ausw&auml;hlen, was mit einem Kombinationsfeld geschieht. Im zweiten Beispiel sollen alle Bestellungen zu einem Kunden aufgelistet werden.<\/p>\n<p><b>Kombinationsfelder f&uuml;llen<\/b><\/p>\n<p>Der interessante Teil beim Abbilden einer 1:n-Beziehung aus Sicht des Bestellungsdatensatzes ist das Kombinationsfeld zum Ausw&auml;hlen des Kunden.<\/p>\n<p>Das Formular zu diesem Beispiel hei&szlig;t <b>frmBestellung<\/b> und zeigt alle Felder der Tabelle <b>tblBestellungen <\/b>an. Die Felder f&uuml;gen Sie am einfachsten wie oben beschrieben hinzu, indem Sie zun&auml;chst die lokale Tabelle <b>tblBestellungen<\/b> als Datenherkunft einstellen, die Felder ins Formular ziehen und die Datenherkunft wieder leeren. Danach legen Sie die folgende Prozedur f&uuml;r das Ereignis <b>Beim Laden <\/b>an:<\/p>\n<pre>Private Sub Form_Load()\r\n    Set Me.Recordset = GetRecordset( _\r\n    GetConnection, _\r\n    &quot;SELECT * FROM tblBestellungen&quot;)\r\nEnd Sub<\/pre>\n<p>Danach funktioniert das Formular gleich wie gew&uuml;nscht &#8211; es zeigt sogar die Daten aus der Tabelle <b>tblKunden <\/b>im Kombinationsfeld zur Auswahl des Kunden an (siehe Bild 3).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_01\/MySQLDirekt-web-images\/pic003_opt.jpeg\" alt=\"pic003.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3: Das Kombinationsfeld ist bereits gef&uuml;llt, aber aus der falschen Quelle.<\/span><\/b><\/p>\n<p>Allerdings stammen diese Daten nat&uuml;rlich nicht vom Webserver, sondern aus der lokalen Tabelle. Die notwendige Datensatzherkunft des Formulars wurde beim Hinzuf&uuml;gen der Felder auf Basis der lokalen Tabelle <b>tblBestellungen<\/b> eingetragen.<\/p>\n<p>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 <b>Datensatzherkunft<\/b>.<\/p>\n<p>Beim n&auml;chsten Wechseln in die Formularansicht ist das Kombinationsfeld leer, was auch logisch ist: Es enth&auml;lt zwar den Wert des Feldes <b>KundeID <\/b>der dem Formular als Recordset zugewiesenen Tabelle <b>tblBestellungen<\/b>, diese wird jedoch nicht angezeigt, weil die Einstellungen der Eigenschaften <b>Spaltenanzahl <\/b>und <b>Spaltenbreiten <\/b>daf&uuml;r ausgelegt sind, den Inhalt des zweiten Felds der Datensatzherkunft des Kombinationsfelds anzuzeigen &#8211; und da diese leer ist, zeigt das Formular eine leere Zeichenkette an. Da es nicht leer ist, k&ouml;nnen Sie durch das Einstellen der Eigenschaften <b>Spaltenanzahl <\/b>und <b>Spaltenbreiten <\/b>auf <b>1 <\/b>und <b>3cm <\/b>nachweisen.<\/p>\n<p><!--30percent--><\/p>\n<p>Damit das Kombinationsfeld die auf dem Webserver gespeicherten Kundennamen zur Auswahl anbietet, m&uuml;ssen wir auch dessen <b>Recordset<\/b>-Eigenschaft mit einem Verweis auf das entsprechend Recordset f&uuml;llen. Dazu erweitern Sie die <b>Beim Laden<\/b>-Ereignisprozedur von oben um die folgende Zeile:<\/p>\n<pre>Set Me!KundeID.Recordset = _\r\nGetRecordset(GetConnection, _\r\n&quot;SELECT KundeID, Nachname &quot; _\r\n    &amp; &quot;FROM tblKunden ORDER BY Nachname&quot;)<\/pre>\n<p>Dies zeigt nun die gew&uuml;nschten Kunden an. Statt des Nachnamens sollen die Kundendaten in einem weiteren Schritt in der Form <b>Nachname, Vorname <\/b>angezeigt werden. Normalerweise w&uuml;rden wir die SQL-Abfrage dazu wie folgt &auml;ndern:<\/p>\n<pre>SELECT KundeID, Nachname &amp; '', '' &amp; Vorname AS Kunde FROM tblKunden ORDER BY Nachname<\/pre>\n<p>Dies funktioniert jedoch nicht: Das Kombinationsfeld zeigt zwar die richtige Anzahl Datens&auml;tze an, allerdings ohne Angabe des Kundennamens.<\/p>\n<p>Der Grund ist einfach: Wenn wir Abfragen wie hier per ADO direkt an den SQL-Server absetzen, m&uuml;ssen diese im SQL-Dialekt des jeweiligen SQL-Servers, hier MySQL, formuliert werden. Und MySQL verwendet zum Konkatenieren von Feldern die <b>CONCAT<\/b>-Funktion. Die SQL-Abfrage muss also so aussehen:<\/p>\n<pre>SELECT KundeID, CONCAT(Nachname, '', '', Vorname) AS Kunde FROM tblKunden ORDER BY Nachname<\/pre>\n<p>Nun zeigt das Kombinationfeld die gew&uuml;nschten Ausdr&uuml;cke an und erlaubt auch deren &auml;nderung. Alternativ k&ouml;nnen Sie auch eine PassThrough-Abfrage als Datensatzherkunft verwenden.<\/p>\n<p><b>1:n-Beziehung mit Unterformular<\/b><\/p>\n<p>Die umgekehrte Ansicht soll alle Bestellungen zu einem Kunden anzeigen. Dazu ben&ouml;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 <b>frmKunden <\/b>aus dem ersten Beispiel weiterverwenden k&ouml;nnen.<\/p>\n<p>Das Unterformular zum Anzeigen der Bestellungen soll <b>sfmKunden <\/b>hei&szlig;en und erh&auml;lt zun&auml;chst die Tabelle <b>tblBestellungen <\/b>als Datenherkunft, damit Sie die gebundenen Felder schnell zum Entwurf hinzuf&uuml;gen k&ouml;nnen. Danach leeren Sie die Datenherkunft, schlie&szlig;en das Formular und f&uuml;gen es dem Formular <b>frmKunden <\/b>als Unterformular hinzu &#8211; am einfachsten gelingt dies, indem Sie <b>frmKunden <\/b>im Entwurf &ouml;ffnen und das Formular <b>sfmKunden <\/b>aus dem Datenbankfenster in den Detailbereich ziehen. Das Ergebnis sieht dann wie in Bild 4 aus. &auml;ndern Sie den Steuerelementtyp des Felds <b>KundeID <\/b>in Textfeld &#8211; es dient sp&auml;ter nur der Pr&uuml;fung, ob das Feld den richtigen Standardwert aufweist, und kann anschlie&szlig;end entfernt werden.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_01\/MySQLDirekt-web-images\/pic004_opt.jpeg\" alt=\"pic004.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4: Kunden und ihre Bestellungen in Haupt- und Unterformular<\/span><\/b><\/p>\n<p>Wenn Sie nun nur das Unterformularsteuerelement markieren und im Eigenschaftsfenster zur Registerseite <b>Daten <\/b>wechseln, finden Sie die beiden Eigenschaften <b>Verkn&uuml;pfen von <\/b>und <b>Verkn&uuml;pfen nach <\/b>leer vor. Normalerweise sollte Access automatisch die Beziehung zwischen den beiden Tabellen <b>tblKunden <\/b>und <b>tblBestellungen <\/b>erkennen und das Feld <b>KundeID <\/b>f&uuml;r beide Eigenschaften eintragen. Dies f&uuml;hrt normalerweise dazu, dass das Unterformular automatisch nur die Bestellungen zu dem im Hauptformular angezeigten Kunden darstellt.<\/p>\n<p>Hier geschieht das nicht, was leicht zu erkl&auml;ren ist: Beide Formulare besitzen schlicht und einfach keine Datenherkunft, da diese ja erst zur Laufzeit hinzugef&uuml;gt wird. Somit kann Access auch keine Beziehung zwischen den im Haupt- und im Unterformular angezeigten Daten erkennen.<\/p>\n<p>Damit wir &uuml;berhaupt eine Chance haben, diese Synchronisierung zu erhalten, m&uuml;ssen wir zun&auml;chst das Unterformular mit Daten f&uuml;llen. Dazu gibt es nun theoretisch zwei M&ouml;glichkeiten:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Sie f&uuml;llen das Unterformular mit allen Daten der Tabelle <b>tblBestellungen <\/b>und f&uuml;gen anschlie&szlig;end die Werte f&uuml;r die Eigenschaften <b>Verkn&uuml;pfen von <\/b>und <b>Verkn&uuml;pfen nach <\/b>manuell hinzu. Access sollte dann eigentlich nur die betroffenen Bestellungen im Unterformular anzeigen.<\/li>\n<li class=\"aufz-hlung\">Sie f&uuml;llen das Unterformular nur mit den Daten, die zum aktuell im Hauptformular angezeigten Kunden geh&ouml;ren.<\/li>\n<\/ul>\n<p>Der Versuch der ersten Variante zeigt, dass sich Theorie und Praxis unterscheiden: Bei per <b>Recordset<\/b>-Eigenschaft zugewiesenen Datenherk&uuml;nften wirken sich die Eigenschaften <b>Verkn&uuml;pfen von <\/b>und <b>Verkn&uuml;pfen nach <\/b>nicht aus. Widmen wir uns also gleich der zweiten Variante, die neben dem F&uuml;llen des Hauptformulars im Ereignis <b>Beim Laden <\/b>des Formulars noch eine weitere Ereignisprozedur einsetzt: Damit das Unterformular jeweils die passenden Bestelldatens&auml;tze zum Kunden des Hauptformulars liefert, sollte dieses bei jedem Wechsel des Datensatzes im Hauptformular aktualisiert werden. Die passende Ereigniseigenschaft hei&szlig;t <b>Beim Anzeigen <\/b>und wird mit folgender Ereignisprozedur zum Leben erweckt:<\/p>\n<pre>Private Sub Form_Current()\r\n    Dim strSQL As String\r\n    Dim lngKundeID As Long\r\n    lngKundeID = Nz(Me!KundeID)\r\n    strSQL = &quot;SELECT * FROM tblBestellungen &quot; _\r\n    &quot;WHERE KundeID = &quot; &amp; lngKundeID\r\n    Set Me!sfmKunden.Form.Recordset = _\r\n    GetRecordset(GetConnection, strSQL)\r\nEnd Sub<\/pre>\n<p>Wir pr&uuml;fen hier, ob das Feld <b>KundeID <\/b>einen Nullwert enth&auml;lt, und ersetzen diesen f&uuml;r die Formulierung der Abfrage durch <b>0<\/b>. Dies hat den Hintergrund, dass der Benutzer mit dem Formular auch neue Datens&auml;tze anlegen k&ouml;nnen soll.<\/p>\n<p>Bei begrenzter Anzahl Datens&auml;tze im Unterformular kann man diese auch gleich komplett laden und beim Wechsel des Datensatzes im Hauptformular einen entsprechenden Filter setzen.<\/p>\n<p>Ein neuer Datensatz besitzt allerdings zun&auml;chst keinen Wert f&uuml;r das Feld <b>KundeID<\/b>. Wenn nun einfach der stattdessen vorhandene Nullwert an die <b>WHERE<\/b>-Bedingung angeh&auml;ngt wird, erzeugt dies einen Fehler, weil MySQL (genauso wenig wie Access-SQL) die <b>WHERE<\/b>-Klausel der Abfrage <b>SELECT * FROM tblBestellungen WHERE KundeID = <\/b>nicht interpretieren kann und einen Fehler ausl&ouml;st.<\/p>\n<p>Es gibt noch ein weiteres kleines Problem, das durch die fehlende Synchronisierung &uuml;ber die Eigenschaften <b>Verkn&uuml;pfen von <\/b>und <b>Verkn&uuml;pfen nach <\/b>hervorgerufen wird: Das Fremdschl&uuml;sselfeld des Datensatzes im Unterformular (<b>Verkn&uuml;pfen von<\/b>) wird nicht automatisch mit dem Prim&auml;rschl&uuml;sselfeld des Datensatzes im Hauptformular (<b>Verkn&uuml;pfen nach<\/b>) gef&uuml;llt. Sie m&uuml;ssen also auch noch daf&uuml;r Sorge tragen, dass der Standardwert dieses Felds entsprechend vorbelegt wird. Da dieser Wert wiederum vom Datensatz im Hauptformular abh&auml;ngt, muss er bei jedem Datensatzwechsel im Hauptformular aktualisiert werden. Dies erledigen wir durch Anh&auml;ngen der folgenden Zeilen an die oben bereits beschriebene Prozedur <b>Form_Current <\/b>des Hauptformulars:<\/p>\n<pre>Me!sfmKunden.Form!KundeID.DefaultValue = lngKundeID<\/pre>\n<p>Dies reicht aus, um den Standardwert von <b>KundeID <\/b>f&uuml;r Bestellungen aller bereits vorhandenen Kunden einzustellen (siehe Bild 5). Leider geschieht dies scheinbar nicht, wenn Sie einen Kundendatensatz anlegen: Beim <b>Form_Current<\/b>-Ereignis, das beim Wechseln zum neuen Datensatz ausgel&ouml;st wird, ist <b>KundeID <\/b>im Hauptformular noch <b>Null<\/b>. Das Fremdschl&uuml;sselfeld im Unterformular wird zwar richtigerweise auch auf <b>Null <\/b>eingestellt, aber nach dem Erzeugen des Autowerts f&uuml;r <b>KundeID <\/b>nach Eingabe des ersten Zeichens in einem Feld des neuen Datensatzes bleibt der Standardwert f&uuml;r <b>KundeID <\/b>im Unterformular auf dem Wert <b>Null <\/b>stehen. Wenn Sie nun im Hauptformular zum vorherigen Datensatz und wieder zur&uuml;ck wechseln, zeigt das Unterformular zwar den richtigen Standardwert an, aber das ist nat&uuml;rlich nicht besonders ergonomisch. Der Benutzer m&ouml;chte m&ouml;glicherweise gleich nach dem Anlegen eines Datensatzes im Hauptformular Daten im Unterformular anlegen (okay, vielleicht nicht in diesem Beispiel, aber es ist ja auch nur ein Beispiel).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_01\/MySQLDirekt-web-images\/pic005_opt.jpeg\" alt=\"pic005.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 5: Der Standardwert der Kunden-ID im Unterformular wird per Code eingestellt.<\/span><\/b><\/p>\n<p>Also sorgen wir daf&uuml;r, dass Access den Standardwert sp&auml;testens beim Eintritt in das Unterformular setzt, und zwar mit folgender Ereignisprozedur:<\/p>\n<pre>Private Sub sfmKunden_Enter()\r\n    Dim lngKundeID As Long\r\n    lngKundeID = Nz(Me!KundeID)\r\n    Me!sfmKunden.Form!KundeID.DefaultValue = lngKundeID\r\nEnd Sub<\/pre>\n<p>Beachten Sie an dieser Stelle, dass die <b>DefaultValue<\/b>-Eigenschaft nur f&uuml;r Steuerelemente zur Verf&uuml;gung steht und nicht f&uuml;r Feldverweise. In den meisten F&auml;llen &auml;ndern Access-Entwickler die Steuerelementnamen von Feldern nach dem Hinzuf&uuml;gen &uuml;ber die Feldliste nicht explizit, was dazu f&uuml;hrt, dass Steuerelement und Feld beziehungsweise Steuerelementinhalt die gleiche Bezeichnung tragen.<\/p>\n<p>Wenn nun das Fremdschl&uuml;sselfeld, dessen Wert Sie per <b>DefaultValue <\/b>vorbelegen m&ouml;chten, nur in der Datenherkunft des Formulars enthalten ist, aber nicht als Steuerelementinhalt eines Steuerelements vorliegt, erzeugt dies einen Fehler. Sie m&uuml;ssen das Fremdschl&uuml;sselfeld also auf jeden Fall zum Formular hinzuf&uuml;gen, was in Bild 5 ja auch geschehen ist. Der Nachteil dabei ist, dass Sie dieses Feld eigentlich gar nicht ben&ouml;tigen &#8211; genau genommen soll es &uuml;berhaupt nicht angezeigt werden, weil ja der Datensatz im Hauptformular bereits zeigt, wozu die Datens&auml;tze im Unterformular geh&ouml;ren.<\/p>\n<p>Macht ja nichts, dann blenden wir es halt durch Einstellen der Eigenschaft <b>Sichtbar <\/b>auf den Wert <b>Nein <\/b>einfach aus. Nur: Dies wirkt sich zwar auf die Formular- und die Endlosansicht, nicht aber auf die Datenblattansicht im Unterformular aus. In der Datenblattansicht gelten andere Gesetze &#8211; es gibt n&auml;mlich einige weitere Eigenschaften f&uuml;r die dort angezeigten Steuerelemente. In diesem Fall erweitern wir die <b>Beim Anzeigen<\/b>-Ereignisprozedur um folgende Zeile, um die Spalte mit dem Feld <b>KundeID <\/b>auszublenden:<\/p>\n<pre>Me!sfmKunden.Form!KundeID.ColumnHidden = True<\/pre>\n<p>Dies k&ouml;nnen Sie &uuml;brigens nur wieder r&uuml;ckg&auml;ngig machen, indem Sie <b>ColumnHidden <\/b>f&uuml;r das entsprechende Steuerelement wieder auf <b>False <\/b>einstellen. Mehr zu diesem Thema erfahren Sie im Beitrag <b>Datenblattansicht aufgebohrt <\/b>(Shortlink 464).<\/p>\n<p><b>m:n-Beziehung mit Unterformular<\/b><\/p>\n<p>Ein typischer Fall f&uuml;r die Anzeige einer m:n-Beziehung im Unterformular sind die Bestellpositionen einer Bestellung. Das Hauptformular zeigt dabei die Bestelldetails wie Kunde, Bestelldatum et cetera an, das Unterformular steuert die bestellten Artikel sowie Informationen wie Anzahl und Preis bei. Im Unterformular muss dabei zwangsl&auml;ufig die Verkn&uuml;pfungstabelle (in unserem Datenmodell <b>tblPositionen<\/b>) auftauchen.<\/p>\n<p>Brauchen wir auch Daten aus der Tabelle <b>tblArtikel<\/b> Nein, in diesem Fall nicht: Denn die zum Zeitpunkt der Bestellung wichtigen Artikelinformationen sollten in die Tabelle <b>tblPositionen <\/b>&uuml;bertragen und nicht einfach nur verkn&uuml;pft werden. Dies betrifft vor allem den Einzelpreis, der sich ja durchaus mit der Zeit &auml;ndern kann, was sich nicht auf bereits durchgef&uuml;hrte Bestellungen auswirken darf. Au&szlig;erdem kann es auch passieren, dass der Einzelpreis eines Artikels bei einer Bestellung ge&auml;ndert werden soll. Wir brauchen also nur die Tabelle <b>tblPositionen<\/b> im Unterformular.<\/p>\n<p>Fangen wir jedoch beim Hauptformular an: Hier k&ouml;nnen wir einfach mit dem bereits weiter oben erstellten Formular <b>frmBestellungen <\/b>fortfahren.<\/p>\n<p>Wir brauchen nun ein Unterformular, das wie in Bild 6 aussieht. Die Datenherkunft <b>tblPositionen <\/b>werfen wir nach dem Hinzuf&uuml;gen der Steuerelemente aus der Feldliste wieder heraus. Gleiches gilt f&uuml;r die Datensatzherk&uuml;nfte der beiden Kombinationsfelder <b>BestellungID <\/b>und <b>ArtikelID<\/b>.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_01\/MySQLDirekt-web-images\/pic006_opt.jpeg\" alt=\"pic006.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 6: Das Unterformular zur Anzeige der Positionen einer Bestellung<\/span><\/b><\/p>\n<p>Au&szlig;erdem k&ouml;nnen wir das Kombinationsfeld <b>BestellungID <\/b>in ein Textfeld &auml;ndern, damit wir gleich den noch zu erstellenden <b>DefaultValue <\/b>kontrollieren k&ouml;nnen &#8211; sp&auml;ter wird dieses Feld nat&uuml;rlich ausgeblendet. Stellen Sie die Eigenschaft <b>Standardansicht <\/b>des angehenden Unterformulars auf <b>Datenblatt <\/b>ein und speichern Sie es unter dem Namen <b>sfmBestellungen<\/b>.<\/p>\n<p>&Ouml;ffnen Sie dann <b>frmBestellungen <\/b>in der Entwurfsansicht und f&uuml;gen Sie <b>sfmBestellungen <\/b>als Unterformular hinzu. Da weder Haupt- noch Unterformular eine Datenherkunft besitzen, werden auch die beiden Eigenschaften <b>Verkn&uuml;pfen von <\/b>und <b>Verkn&uuml;pfen nach <\/b>des Unterformularsteuerelements automatisch gef&uuml;llt.<\/p>\n<p>Schauen wir uns nun die notwendigen Prozeduren an, um Haupt- und Unterformular zu f&uuml;llen. Den Start macht das Hauptformular mit mit der Ereignisprozedur aus Listing 1, die beim Laden des Formulars ausgel&ouml;st wird. Sie weist dem <b>Recordset<\/b>-Objekt zuerst eine Datensatzgruppe mit allen Datens&auml;tzen der Tabelle <b>tblBestellungen <\/b>zu und f&uuml;llt das Kombinationsfeld <b>KundeID <\/b>mit allen vorhandenen Kunden. Gleiches geschieht mit dem Kombinationsfeld <b>ArtikelID <\/b>aus dem Unterformular: Dieses soll dem Benutzer alle vorhandenen Artikel zur Auswahl anbieten. Schlie&szlig;lich blendet die Prozedur die beiden Felder <b>PositionID <\/b>und <b>BestellungID <\/b>im Unterformular aus.<\/p>\n<p class=\"kastentabelleheader\">Listing 1: F&uuml;llen des Hauptformulars beim Laden<\/p>\n<pre>Private Sub Form_Load()\r\n    Set Me.Recordset = GetRecordset(GetConnection, \"SELECT * FROM tblBestellungen\")\r\n    Set Me!KundeID.Recordset = GetRecordset(GetConnection, _\r\n    \"SELECT KundeID, CONCAT(Nachname, &euro;, &euro;, Vorname) AS Kunde FROM tblKunden ORDER BY Nachname\")\r\n    With Me!sfmBestellungen.Form\r\n        Set !ArtikelID.Recordset = GetRecordset(GetConnection, _\r\n        \"SELECT ArtikelID, Artikelname, Artikelpreis FROM tblArtikel\")\r\n        !PositionID.ColumnHidden = True\r\n        !BestellungID.ColumnHidden = True\r\n    End With\r\nEnd Sub<\/pre>\n<p>Die Prozedur aus Listing 2 wird jeweils beim Wechseln des Datensatzes im Hauptformular ausgel&ouml;st und sorgt daf&uuml;r, dass die zur Bestellung passenden Positionen im Unterformular angezeigt werden. Dazu pr&uuml;ft die Prozedur zun&auml;chst die <b>BestellungID <\/b>auf den Wert <b>Null, <\/b>ersetzt diesen gegebenenfalls durch die Zahl <b>0<\/b> und schreibt das Ergebnis in die <b>Long<\/b>-Variable <b>lngBestellungID<\/b>.<\/p>\n<p class=\"kastentabelleheader\">Listing 2: Aktualisieren des Unterformulars beim Anzeigen eines neuen Datensatzes im Hauptformular<\/p>\n<pre>Private Sub Form_Current()\r\n    Dim lngBestellungID As Long\r\n    lngBestellungID = Nz(Me!BestellungID)\r\n    With Me!sfmBestellungen.Form\r\n    Set .Recordset = GetRecordset(GetConnection, _\r\n        \"SELECT * FROM tblPositionen WHERE BestellungID = \" &amp; lngBestellungID)\r\n        !BestellungID.DefaultValue = lngBestellungID\r\n    End With\r\nEnd Sub<\/pre>\n<p>Diese dient als Vergleichswert f&uuml;r die <b>WHERE<\/b>-Klausel der Abfrage, welche die Positionen zur aktuellen Bestellung ermittelt und das resultierende Recordset der gleichnamigen Eigenschaft des Unterformulars zuweist. Damit das Unterformular neue Datens&auml;tze gleich der richtigen Bestellung zuordnen kann, stellt die Prozedur noch den Standardwert des Felds <b>BestellungID <\/b>auf den entsprechenden Wert der im Hauptformular angegebenen Bestellung ein.<\/p>\n<p>Die Prozedur aus Listing 3 beugt dem Fall vor, dass der Benutzer eine neue Bestellung anlegt und dann die gew&uuml;nschten Positionen hinzuf&uuml;gen m&ouml;chte. Daf&uuml;r gibt es zwei Varianten:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Wenn der Benutzer bereits Daten im Hauptformular eingetragen hat, gibt es auch schon eine <b>BestellungID<\/b>. Diese wird dann beim Eintreten in das Unterformular als Standardwert f&uuml;r das Steuerelement <b>BestellungID <\/b>des Unterformulars angegeben.<\/li>\n<li class=\"aufz-hlung\">Falls der Benutzer im Hauptformular noch keine Daten eintragen hat, besitzt das Autowert-Feld <b>BestellungID <\/b>auch noch keinen Wert. In diesem Fall wird der Benutzer zun&auml;chst zum Hauptformular zur&uuml;ckgeschickt, um einen Bestellungs-Datensatz zu erzeugen.<\/li>\n<\/ul>\n<p class=\"kastentabelleheader\">Listing 3: Einstellen des Fremdschl&uuml;sselfelds beim Eintreten ins Unterformular bei neuen Bestellungen<\/p>\n<pre>Private Sub sfmBestellungen_Enter()\r\n    Dim lngBestellungID As Long\r\n    lngBestellungID = Nz(Me!BestellungID)\r\n    If Not lngBestellungID = 0 Then\r\n        Me!sfmBestellungen.Form!BestellungID.DefaultValue = lngBestellungID\r\n    Else\r\n        MsgBox !Bitte geben Sie zun&auml;chst die Bestellinformationen wie Kunde und Bestelldatum an.\", _\r\n        vbOKOnly + vbExclamation, \"Bestelldaten fehlen\"\r\n        Me!Bestelldatum.SetFocus\r\n    End If\r\nEnd Sub<\/pre>\n<p>Schlie&szlig;lich m&uuml;ssen wir uns bei Verwendung von ADO-Recordsets in Haupt- und Unterformular noch darum k&uuml;mmern, dass beim L&ouml;schen des Datensatzes im Hauptformular auch die damit verkn&uuml;pften Daten im Unterformular gel&ouml;scht werden &#8211; es sei denn, Sie haben auf dem MySQL-Server L&ouml;schweitergabe aktiviert (was nur bei MySQL 5-Tabellen im <b>InnoDB<\/b>-Format funktioniert). Falls nicht, erledigt die Prozedur aus Listing 4 dies f&uuml;r Sie.<\/p>\n<p class=\"kastentabelleheader\">Listing 4: L&ouml;schen der verkn&uuml;pften Positionen beim L&ouml;schen einer Bestellung<\/p>\n<pre>Private Sub Form_Delete(Cancel As Integer)\r\n    GetConnection.Execute \"DELETE FROM tblPositionen WHERE BestellungID = \" &amp; Me!BestellungID\r\nEnd Sub<\/pre>\n<p><b>Behandlung von Abfragen &uuml;ber mehr als eine Tabelle<\/b><\/p>\n<p>Bislang konnten wir alle gew&uuml;nschten Beziehungen in entsprechenden Formularen abbilden. Es gibt allerdings auch F&auml;lle, denen nur mit gr&ouml;&szlig;erem Aufwand beizukommen ist. Dabei handelt es sich grunds&auml;tzlich um Formulare, die Daten aus mehr als einer Tabelle anzeigen sollen und deren Datenherkunft entsprechend aus einer Abfrage mit mehreren per <b>JOIN<\/b> verkn&uuml;pften Tabellen besteht.<\/p>\n<p>Das Problem ist, dass Access im Gegensatz zu anderen Datenbanksystemen sehr gro&szlig;z&uuml;gig bez&uuml;glich der Aktualisierung von Daten aus verkn&uuml;pften Tabellen ist. Beim F&uuml;llen des Recordsets eines Formulars mit zwei oder mehr verkn&uuml;pften Tabellen aus einer MySQL-Datenbank via ADODB sieht das zum Beispiel anders aus: Die Daten werden dann zwar angezeigt, k&ouml;nnen allerdings nicht bearbeitet werden. Wenn man dies von vornherein wei&szlig;, kann man das Design seiner Benutzeroberfl&auml;che auch mit dieser Einschr&auml;nkung in den meisten F&auml;llen ausreichend gut umsetzen.<\/p>\n<p>Beim Umstellen bestehender Datenbanken auf ADODB-\/Recordset-Technik kann es hier und da schon einmal zu Problemen kommen, beispielsweise wenn Felder aus verkn&uuml;pften Tabellen als <b>WHERE<\/b>-Bedingung oder als Sortierung per <b>ORDER BY<\/b>-Klausel verwendet werden; noch schwieriger wird es, wenn Daten aus mehr als einer Tabelle in einem Formular bearbeitet werden sollen.<\/p>\n<p><b>Sortier- und sonstige Kriterien aus verkn&uuml;pften Tabellen<\/b><\/p>\n<p>Wenn Sie Daten einer Tabelle anzeigen m&ouml;chten und nach Feldern aus verkn&uuml;pften Tabellen sortieren oder filtern m&ouml;chten, d&uuml;rfen diese nicht in der Ergebnismenge der Abfrage enthalten sein. Die folgende Abfrage w&uuml;rde beispielsweise ein Aktualisieren der angezeigten Daten verhindern:<\/p>\n<pre>SELECT tblBestellungen.BestellungID,\r\ntblBestellungen.Bestelldatum, tblKunden.Vorname, tblKunden.Nachname\r\nFROM tblKunden\r\nINNER JOIN tblBestellungen\r\nON tblKunden.KundeID = tblBestellungen.KundeID\r\nWHERE tblKunden.Vorname LIKE ''Andre'';<\/pre>\n<p>Wenn Sie die Ergebnismenge wie folgt auf die Felder einer einzigen Tabelle beschr&auml;nken, k&ouml;nnen Sie die Daten bearbeiten und l&ouml;schen und auch neue Datens&auml;tze anlegen:<\/p>\n<pre>SELECT tblBestellungen.BestellungID,\r\ntblBestellungen.Bestelldatum\r\nFROM tblKunden ...<\/pre>\n<p>Sollten Daten ohnehin nur der Anzeige dienen wie etwa die in Recordsets von Kombinations- oder Listenfeldern, k&ouml;nnen Sie sich beim Zusammenstellen der zugrunde liegenden Abfragen austoben.<\/p>\n<p>Wir beschr&auml;nken uns an dieser Stelle darauf, auf potenzielle Probleme hinzuweisen. Theoretisch ist es immer m&ouml;glich, Tabellen, Abfragen und Formulare so zu gestalten, dass Inhalte aus nicht mehr als einer Tabelle dargestellt beziehungsweise bearbeitet werden m&uuml;ssen.<\/p>\n<p><b>ADODB-Recordsets in Berichten<\/b><\/p>\n<p>Wer Formulare und Steuerelemente mit ADO-Recordsets bef&uuml;llt, kommt fr&uuml;her oder sp&auml;ter nat&uuml;rlich auf die Idee, dies mit einem Bericht durchzuf&uuml;hren. Leider k&ouml;nnen Berichte auch mit Access 2007 noch immer nicht mit benutzerdefinierten Recordsets gef&uuml;llt werden. Als Alternative empfiehlt es sich, eine <b>PassThrough<\/b>-Abfrage zu verwenden, die bez&uuml;glich der Geschwindigkeit wohl eine &auml;hnliche Leistung erwarten l&auml;sst.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Wenn Sie mit einem Access-Frontend auf eine Datenbank zugreifen m&ouml;chten, die auf einem Webserver liegt (was aktuell meist ein MySQL-Server sein d&uuml;rfte) und sich &uuml;ber die m&auml;&szlig;ige Geschwindigkeit bei der Verwendung verkn&uuml;pfter ODBC-Tabellen &auml;rgern, finden Sie in diesem Beitrag m&ouml;glicherweise die L&ouml;sung: Am Beispiel einer im Einsatz befindlichen Anwendung konnte der Autor deutliche Performance-Steigerungen feststellen, welche die Umstellung der kompletten Anwendung auf die hier vorgestellte Technik nach sich zog. Gleichwohl muss klar sein, dass der Programmieraufwand etwas h&ouml;her ist als bei der Verwendung eingebundener ODBC-Tabellen, was ja im Prinzip mit dem f&uuml;r den Einsatz lokaler Tabellen n&ouml;tigen Aufwand vergleichbar ist. Au&szlig;erdem sind hier und da Umstellungen erforderlich, da Datenherk&uuml;nfte mit Daten aus mehreren verkn&uuml;pften Tabellen unter Umst&auml;nden nicht aktualisiert werden k&ouml;nnen.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>ADODB_MySQL.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{318E235C-9718-4250-BC1E-FBCC51C43C6D}\/aiu_702.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wer einen Webserver sein Eigen nennt oder anderweitig Gelegenheit zum Ablegen von Daten in einer MySQL-Datenbank hat, kann dies f&uuml;r verschiedene Zwecke nutzen: Prim&auml;r sollen Datenbanken auf Webservern nat&uuml;rlich Inhalte f&uuml;r Internetseiten liefern, aber Sie k&ouml;nnen diese nat&uuml;rlich auch einfach als zentrale Datenbasis verwenden und von &uuml;berall auf diese zugreifen. Wenn dies auch noch in akzeptabler Zeit gelingen soll, m&uuml;ssen Sie jedoch einige Regeln beachten.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66012010,662010,44000023,44000022],"tags":[],"class_list":["post-55000702","post","type-post","status-publish","format-standard","hentry","category-66012010","category-662010","category-Mit_Formularen_arbeiten","category-SQL_Server_und_Co"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Performanter Webzugriff auf MySQL-Datenbanken - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Performanter Webzugriff auf MySQL-Datenbanken\" \/>\n<meta property=\"og:description\" content=\"Wer einen Webserver sein Eigen nennt oder anderweitig Gelegenheit zum Ablegen von Daten in einer MySQL-Datenbank hat, kann dies f&uuml;r verschiedene Zwecke nutzen: Prim&auml;r sollen Datenbanken auf Webservern nat&uuml;rlich Inhalte f&uuml;r Internetseiten liefern, aber Sie k&ouml;nnen diese nat&uuml;rlich auch einfach als zentrale Datenbasis verwenden und von &uuml;berall auf diese zugreifen. Wenn dies auch noch in akzeptabler Zeit gelingen soll, m&uuml;ssen Sie jedoch einige Regeln beachten.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T22:10:40+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg05.met.vgwort.de\/na\/1e33a7deee0e49f4af3c5e6034795928\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"24\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Performanter Webzugriff auf MySQL-Datenbanken\",\"datePublished\":\"2020-05-22T22:10:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/\"},\"wordCount\":4394,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/1e33a7deee0e49f4af3c5e6034795928\",\"articleSection\":[\"1\\\/2010\",\"2010\",\"Mit Formularen arbeiten\",\"SQL Server und Co.\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/\",\"name\":\"Performanter Webzugriff auf MySQL-Datenbanken - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/1e33a7deee0e49f4af3c5e6034795928\",\"datePublished\":\"2020-05-22T22:10:40+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/1e33a7deee0e49f4af3c5e6034795928\",\"contentUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/1e33a7deee0e49f4af3c5e6034795928\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Performanter_Webzugriff_auf_MySQLDatenbanken\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Performanter Webzugriff auf MySQL-Datenbanken\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Performanter Webzugriff auf MySQL-Datenbanken - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/","og_locale":"de_DE","og_type":"article","og_title":"Performanter Webzugriff auf MySQL-Datenbanken","og_description":"Wer einen Webserver sein Eigen nennt oder anderweitig Gelegenheit zum Ablegen von Daten in einer MySQL-Datenbank hat, kann dies f&uuml;r verschiedene Zwecke nutzen: Prim&auml;r sollen Datenbanken auf Webservern nat&uuml;rlich Inhalte f&uuml;r Internetseiten liefern, aber Sie k&ouml;nnen diese nat&uuml;rlich auch einfach als zentrale Datenbasis verwenden und von &uuml;berall auf diese zugreifen. Wenn dies auch noch in akzeptabler Zeit gelingen soll, m&uuml;ssen Sie jedoch einige Regeln beachten.","og_url":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T22:10:40+00:00","og_image":[{"url":"http:\/\/vg05.met.vgwort.de\/na\/1e33a7deee0e49f4af3c5e6034795928","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"24\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Performanter Webzugriff auf MySQL-Datenbanken","datePublished":"2020-05-22T22:10:40+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/"},"wordCount":4394,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/1e33a7deee0e49f4af3c5e6034795928","articleSection":["1\/2010","2010","Mit Formularen arbeiten","SQL Server und Co."],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/","url":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/","name":"Performanter Webzugriff auf MySQL-Datenbanken - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/1e33a7deee0e49f4af3c5e6034795928","datePublished":"2020-05-22T22:10:40+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/#primaryimage","url":"http:\/\/vg05.met.vgwort.de\/na\/1e33a7deee0e49f4af3c5e6034795928","contentUrl":"http:\/\/vg05.met.vgwort.de\/na\/1e33a7deee0e49f4af3c5e6034795928"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Performanter_Webzugriff_auf_MySQLDatenbanken\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Performanter Webzugriff auf MySQL-Datenbanken"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000702","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55000702"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000702\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000702"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000702"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000702"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}