{"id":55000447,"date":"2024-12-01T00:00:00","date_gmt":"2025-03-10T20:14:57","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=447"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"ADODB_SQLBefehle_schnell_ausfuehren_mit_Execute","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/ADODB_SQLBefehle_schnell_ausfuehren_mit_Execute\/","title":{"rendered":"ADODB: SQL-Befehle schnell ausf&uuml;hren mit Execute"},"content":{"rendered":"<p><b>ADODB bietet verschiedene Techniken, um SQL-Befehle zum Abfragen oder &Auml;ndern von Daten auszuf&uuml;hren. Die bekannteste zum Abfragen von Daten d&uuml;rfte die OpenRecordset-Methode sein. F&uuml;r das Ausf&uuml;hren von Anweisungen kann man f&uuml;r vollen Komfort am besten die Command-Klasse mit der Execute-Methode verwenden. Aber auch die Connection-Klasse bietet bereite eine Execute-Methode an. Mit dieser l&auml;sst sich schnell und flexibel Einiges erledigen. Welche M&ouml;glichkeiten sie bietet und wie wir diese f&uuml;r den Datenzugriff nutzen k&ouml;nnen, zeigen wir in diesem Artikel.<\/b><\/p>\n<p>Die <b>Execute<\/b>-Methode des <b>Connection<\/b>-Objekts ist die einfachste M&ouml;glichkeit, eine Abfrage zum &Auml;ndern der Daten einer SQL Server-Datenbank auszuf&uuml;hren. Damit k&ouml;nnen wir jedoch nicht nur Daten &auml;ndern, in dem wir eine der folgenden Aktualisierungsabfrage nutzen:<\/p>\n<ul>\n<li><b>DELETE<\/b>: L&ouml;schen von Datens&auml;tzen<\/li>\n<li><b>UPDATE<\/b>: Aktualisieren von Datens&auml;tzen<\/li>\n<li><b>INSERT INTO<\/b>: Einf&uuml;gen von Datens&auml;tzen<\/li>\n<\/ul>\n<p>Wir k&ouml;nnen durch das Ausf&uuml;hren der <b>Execute<\/b>-Methode auch solche SQL-Anweisungen ausf&uuml;hren, mit denen wir den Entwurf des Datenmodells selbst &auml;ndern &#8211; zum Anlegen, &Auml;ndern oder L&ouml;schen von Tabellen, Feldern, Indizes und vielem mehr.<\/p>\n<h2>Erstellen einer Tabelle mit Execute<\/h2>\n<p>Im ersten Beispiel erstellen wir erst einmal eine Tabelle, mit der wir danach weitere Aktionen durchf&uuml;hren. Dieses Beispiel finden wir in Listing 1. Hier deklarieren wir zun&auml;chst ein <b>Connection<\/b>-Objekt sowie eine Zeichenkette zum Speichern der SQL-Anweisung.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabelleErstellen()\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     \r\n     <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n     cnn.ConnectionString = \"Provider=MSOLEDBSQL;Data Source=amvDesktop2023;Initial Catalog=Anlagen;\" _\r\n         & \"Integrated Security=SSPI;\"\r\n     cnn.Open\r\n     \r\n     strSQL = \"CREATE TABLE tblKategorien (\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strSQL = strSQL & \"    KategorieID INT IDENTITY(1,1) PRIMARY KEY,\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strSQL = strSQL & \"    Kategoriebezeichnung VARCHAR(255) NOT NULL\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strSQL = strSQL & \");\"\r\n     cnn.Execute strSQL\r\n     cnn.Close\r\n     <span style=\"color:blue;\">Set<\/span> cnn = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Prozedur zum Erstellen einer Tabelle<\/span><\/b><\/p>\n<p>Danach erstellen wir das <b>Connection<\/b>-Objekt und speichern es in der Variablen <b>cnn<\/b>. Wir weisen die Verbindungszeichenfolge zu und &ouml;ffnen die Verbindung mit der <b>Open<\/b>-Anweisung.<\/p>\n<p>Danach stellen wir in der Variablen <b>strSQL <\/b>die SQL-Anweisung zusammen, die wie folgt aussieht:<\/p>\n<pre>CREATE TABLE tblKategorien (\r\n     KategorieID INT IDENTITY(1,1) PRIMARY KEY,\r\n     Kategoriebezeichnung VARCHAR(255) NOT NULL\r\n);<\/pre>\n<p>Diese brauchen wir nun nur noch mit der <b>Execute<\/b>-Methode des <b>Connection<\/b>-Objekts auszuf&uuml;hren. Damit haben wir bereits eine Tabelle zum Experimentieren angelegt.<\/p>\n<p>Woher wissen wir in diesem Fall, dass das Anlegen erfolgreich war? Ganz einfach dadurch, dass wir keinen Fehler ausgel&ouml;st haben.<\/p>\n<p>Wir k&ouml;nnen die Gegenprobe machen, indem wir die Prozedur einfach erneut aufrufen. Damit versuchen wir, eine Tabelle anzulegen, die bereits vorhanden ist. Dies l&ouml;st einen Fehler aus, der in Access mit der Meldung aus Bild 1 angezeigt wird.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_06\/pic_447_001.png\" alt=\"Fehler beim Versuch, eine Tabelle erneut anzulegen\" width=\"524,6265\" height=\"297,7925\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Fehler beim Versuch, eine Tabelle erneut anzulegen<\/span><\/b><\/p>\n<h2>Datensatz anlegen mit Execute<\/h2>\n<p>Im zweiten Beispiel wollen wir dieser Tabelle einen Datensatz hinzuf&uuml;gen (siehe Listing 2). Dieser soll im Feld <b>Kategoriebezeichnung <\/b>den Wert <b>Beispielkategorie <\/b>erhalten. Das Feld <b>KategorieID <\/b>wird automatisch gef&uuml;llt, da wir dieses mit dem Schl&uuml;sselwort <b>IDENTITY(1,1) <\/b>als Autowertfeld definiert haben.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>DatensatzHinzufuegen()\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     \r\n     <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n     cnn.ConnectionString = \"Provider=MSOLEDBSQL;Data Source=amvDesktop2023;Initial Catalog=Anlagen;\" _\r\n         & \"Integrated Security=SSPI;\"\r\n     cnn.Open\r\n     \r\n     strSQL = \"INSERT INTO tblKategorien(Kategoriebezeichnung) VALUES(''Beispielkategorie'')\"\r\n     cnn.Execute strSQL\r\n     cnn.Close\r\n     <span style=\"color:blue;\">Set<\/span> cnn = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Prozedur zum Hinzuf&uuml;gen eines Datensatzes<\/span><\/b><\/p>\n<p>Auch diese Anweisung f&uuml;hren wir mit der <b>Execute<\/b>-Methode aus. Das Ergebnis ist ein neuer Datensatz in der Tabelle <b>tblKategorien<\/b>.<\/p>\n<h2>Anzahl angelegter Datens&auml;tze ermitteln<\/h2>\n<p>Wie k&ouml;nnen wir hier ermitteln, ob das Anlegen erfolgreich war? Dazu ermitteln wir die Anzahl der von der Abfrage betroffenen Datens&auml;tze (siehe Listing 3).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>DatensatzHinzufuegenMitErgebnis()\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngRecordsAffected<span style=\"color:blue;\"> As Long<\/span>\r\n     \r\n     <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n     cnn.ConnectionString = \"Provider=MSOLEDBSQL;Data Source=amvDesktop2023;Initial Catalog=Anlagen;\" _\r\n         & \"Integrated Security=SSPI;\"\r\n     cnn.Open\r\n     \r\n     strSQL = \"INSERT INTO tblKategorien(Kategoriebezeichnung) VALUES(''Beispielkategorie'')\"\r\n     cnn.Execute strSQL, lngRecordsAffected\r\n     <span style=\"color:blue;\">MsgBox<\/span> \"Anzahl angelegter Datens&auml;tze: \" & lngRecordsAffected\r\n     cnn.Close\r\n     <span style=\"color:blue;\">Set<\/span> cnn = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Prozedur zum Hinzuf&uuml;gen eines Datensatzes mit Ergebnis<\/span><\/b><\/p>\n<p>Diese Information k&ouml;nnen wir aus dem zweiten Parameter der <b>Execute<\/b>-Anweisung entnehmen. Dieser m&uuml;ssen wir dazu eine zuvor deklarierte Variable &uuml;bergeben. Sie wird dann beim Ausf&uuml;hren der Abfrage mit der Anzahl der betroffenen Datens&auml;tze gef&uuml;llt.<\/p>\n<p>Das Ergebnis der Abfrage geben wir dann in einer Meldung aus.<\/p>\n<p>Aber kann es beim Anlegen von Datens&auml;tzen &uuml;berhaupt ein anderes Ergebnis als <b>1 <\/b>geben? Nein, das ist nicht der Fall. Es kann lediglich passieren, dass die Abfrage einen Fehler ausl&ouml;st.<\/p>\n<p>Wir k&ouml;nnen hier sogar zwei Datens&auml;tze in aufeinanderfolgenden <b>INSERT INTO<\/b>-Anweisungen einf&uuml;gen. Dazu ersetzen wir die entsprechende Anweisung wie folgt:<\/p>\n<pre>strSQL = \"INSERT INTO tblKategorien(Kategoriebezeichnung) VALUES(''Beispielkategorie'');INSERT INTO tblKategorien(Kategoriebezeichnung) VALUES(''Beispielkategorie1'')\"<\/pre>\n<p>Dies liefert jedoch immer noch den Wert <b>1 <\/b>zur&uuml;ck. Der Grund ist, dass hier immer nur das Ergebnis der zuletzt verwendeten Anweisung genutzt wird.<\/p>\n<p>In T-SQL gibt es jedoch im Gegensatz zu Access-SQL die M&ouml;glichkeit, hinter dem <b>VALUES<\/b>-Schl&uuml;sselwort mehrere Klammernpaare mit den hinzuzuf&uuml;genden Feldwerten anzugeben.<\/p>\n<p>In unserem einfachen Fall mit dem einen Feld sieht das wie folgt aus:<\/p>\n<pre>strSQL = \"INSERT INTO tblKategorien(Kategoriebezeichnung) VALUES(''Beispielkategorie1''), (''Beispielkategorie2'');\"<\/pre>\n<p>Der Aufruf dieser Anweisung liefert tats&auml;chlich den Wert <b>2<\/b> f&uuml;r die Anzahl der betroffenen Datens&auml;tze zur&uuml;ck.<\/p>\n<h2>Datens&auml;tze per INSERT INTO&#8230;SELECT einf&uuml;gen<\/h2>\n<p>Unkomplizierter ist es, wenn wir die einzuf&uuml;genden Daten aus einer <b>SELECT<\/b>-Abfrage beziehen. In diesem Beispiel f&uuml;gen wir einfach alle bereits vorhandenen Datens&auml;tze nochmals zur Tabelle hinzu:<\/p>\n<pre>strSQL = \"INSERT INTO tblKategorien(Kategoriebezeichnung) SELECT Kategoriebezeichnung FROM tblKategorien;\"<\/pre>\n<p>In diesem Fall erhalten wir direkt die korrekte Anzahl der betroffenen Datens&auml;tze.<\/p>\n<h2>Datens&auml;tze per UPDATE aktualisieren<\/h2>\n<p>Wenn wir einen oder mehrere Datens&auml;tze einer Tabelle aktualisieren wollen, nutzen wir die <b>UPDATE<\/b>-Anweisung. Diese rufen wir beispielsweise wie folgt aus (den Rest der Prozedur &uuml;bernehmen wir aus den vorherigen Beispielen):<\/p>\n<pre>strSQL = \"UPDATE tblKategorien SET Kategoriebezeichnung = ''Kategorie'' WHERE KategorieID = 1;\"<\/pre>\n<p>Hier wird die Kategoriebezeichnung aller Datens&auml;tze angepasst, deren Feld <b>KategorieID <\/b>den Wert <b>1 <\/b>aufweist. Dies betrifft in unserem Beispiel genau einen Datensatz.<\/p>\n<pre>strSQL = \"UPDATE tblKategorien SET Kategoriebezeichnung = Kategoriebezeichnung + '' (ge&auml;ndert)'' WHERE Kategoriebezeichnung LIKE ''%Kategorie%'';\"<\/pre>\n<p>Hier wollen wir dem Wert des Feldes <b>Kategoriebezeichnung <\/b>die Zeichenkette <b>(ge&auml;ndert) <\/b>anh&auml;ngen, wenn die Kategoriebezeichnung die Zeichenkette <b>Kategorie <\/b>enth&auml;lt.<\/p>\n<p>Auch hier wird die Anzahl der betroffenen Datens&auml;tze korrekt zur&uuml;ckgeliefert.<\/p>\n<h2>Datens&auml;tze per DELETE l&ouml;schen<\/h2>\n<p>Zum L&ouml;schen eines Datensatzes verwenden wir die folgende Anweisung f&uuml;r die Variable <b>strSQL<\/b>:<\/p>\n<pre>strSQL = \"DELETE FROM tblKategorien WHERE KategorieID = 11;\"<\/pre>\n<p>F&uuml;hren wir diese mit der <b>Execute<\/b>-Methode aus, erhalten wir wiederum die Menge der betroffenen Datens&auml;tze als Ergebnis.<\/p>\n<p>Hier kann es genauso wie bei der <b>UPDATE<\/b>-Anweisung vorkommen, dass 0 Datens&auml;tze betroffen sind, wenn die <b>WHERE<\/b>-Bedingung keine zu &auml;ndernden Datens&auml;tze liefert.<\/p>\n<h2>Der dritte Parameter &#8220;Options&#8221;<\/h2>\n<p>In den bisherigen Beispielen haben wir den dritten Parameternamens <b>Options <\/b>bisher vernachl&auml;ssigt. Dieser kann die folgenden Werte annehmen:<\/p>\n<ul>\n<li><b>adCmdUnknown <\/b>(<b>8<\/b>): Standardwert. Die Art der auszuf&uuml;hrenden Anweisung wird automatisch erkannt.<\/li>\n<li><b>adCmdText <\/b>(<b>1<\/b>): Behandlung des ersten Parameters als Text. Funktioniert f&uuml;r <b>SELECT<\/b>, <b>INSERT<\/b>, <b>UPDATE <\/b>und <b>DELETE<\/b>-Anweisungen.<\/li>\n<li><b>adCmdTable <\/b>(<b>2<\/b>): Kann verwendet werden, wenn als erster Parameter der Name einer Tabelle angegeben wird. Nur f&uuml;r <b>SELECT<\/b>-Abfragen.<\/li>\n<li><b>acCmdStoredProc <\/b>(<b>4<\/b>): Kann f&uuml;r gespeicherte Prozeduren verwendet werden. Diese kann dann ohne das Schl&uuml;sselwort <b>EXEC <\/b>als erster Parameter angegeben werden.<\/li>\n<li><b>adAsyncExecute <\/b>(<b>16<\/b>): Die Anweisung wird asynchron ausgef&uuml;hrt, also im Hintergrund, und die aufrufende Prozedur wird weiter ausgef&uuml;hrt, w&auml;hrend die Abfrage ausgef&uuml;hrt wird.<\/li>\n<\/ul>\n<p>Wir k&ouml;nnen verschiedene Werte f&uuml;r den dritten Parameter kombinieren, indem wir diese addieren.<\/p>\n<p>Sinnvoll ist das jedoch nur, wenn man einen der Werte <b>adCmdUnknown<\/b>, <b>adCmdText<\/b>, <b>adCmdTable <\/b>oder <b>adCmdStoredProc <\/b>mit <b>adAsyncExecute <\/b>kombiniert.<\/p>\n<h2>SELECT-Anweisungen per Execute<\/h2>\n<p>Wir k&ouml;nnen der <b>Execute<\/b>-Methode sogar <b>SELECT<\/b>-Anweisungen &uuml;bergeben. Aber was wollen wir damit machen &#8211; wie wollen wir das Ergebnis erhalten oder weiterverarbeiten?<\/p>\n<p>Die Antwort ist einfach: Wir weisen das Ergebnis eines solchen <b>Execute<\/b>-Aufrufs einfach einem ADODB-Recordset zu.<\/p>\n<p>Als Erstes deklarieren wir dazu ein <b>ADODB.Recordset<\/b>-Objekt namens <b>rst<\/b>. Als Abfrage definieren wir eine <b>SELECT<\/b>-Abfrage.<\/p>\n<p>Das Ergebnis der <b>Execute<\/b>-Methode weisen wir dem Recordset zu und zeigen anschlie&szlig;end, dass es gef&uuml;llt wurde, indem wir dieses durchlaufen (siehe Listing 4).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ExecuteRecordset()\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>ADODB.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     \r\n     <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n     cnn.ConnectionString = \"Provider=MSOLEDBSQL;Data Source=amvDesktop2023;Initial Catalog=Anlagen;\" _\r\n         & \"Integrated Security=SSPI;\"\r\n     cnn.Open\r\n     \r\n     strSQL = \"SELECT * FROM tblKategorien;\"\r\n     \r\n     <span style=\"color:blue;\">Set<\/span> rst = cnn.Execute(strSQL)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         <span style=\"color:blue;\">Debug.Print<\/span> rst!KategorieID, rst!Kategoriebezeichnung\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     cnn.Close\r\n     <span style=\"color:blue;\">Set<\/span> cnn = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Prozedur zum Erstellen eines Recordsets<\/span><\/b><\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Mit der <b>Execute<\/b>-Methode der Connection-Klasse k&ouml;nnen wir schnell SQL-Anweisungen ausf&uuml;hren. Es gibt noch eine <b>Execute<\/b>-Methode f&uuml;r die Command-Klasse, mit der wir &auml;hnliches erledigen k&ouml;nnen. Diese bietet jedoch noch mehr M&ouml;glichkeiten, die wir uns im Artikel  ansehen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>ADODB bietet verschiedene Techniken, um SQL-Befehle zum Abfragen oder &Auml;ndern von Daten auszuf&uuml;hren. Die bekannteste zum Abfragen von Daten d&uuml;rfte die OpenRecordset-Methode sein. F&uuml;r das Ausf&uuml;hren von Anweisungen kann man f&uuml;r vollen Komfort am besten die Command-Klasse mit der Execute-Methode verwenden. Aber auch die Connection-Klasse bietet bereite eine Execute-Methode an. Mit dieser l&auml;sst sich schnell und flexibel Einiges erledigen. Welche M&ouml;glichkeiten sie bietet und wie wir diese f&uuml;r den Datenzugriff nutzen k&ouml;nnen, zeigen wir in diesem Artikel.<\/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":[662024,66062024,44000008],"tags":[],"yst_prominent_words":[],"class_list":["post-55000447","post","type-post","status-publish","format-standard","hentry","category-662024","category-66062024","category-Datenzugriffstechnik"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000447","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000447"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000447\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000447"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000447"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000447"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000447"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}