{"id":55001542,"date":"2025-06-01T00:00:00","date_gmt":"2025-05-07T12:08:13","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1542"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"AnlageFeld_zum_SQL_Server_migrieren","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/","title":{"rendered":"Anlage-Feld zum SQL Server migrieren"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg02.met.vgwort.de\/na\/10edda9852994c5f98780f5748e33207\" width=\"1\" height=\"1\" alt=\"\"><b>Anlage-Felder erlauben es seit Access 2010, Bilder und andere Dateien direkt in Access-Tabellen zu speichern. Sie bieten ein praktisches Popup-Men&uuml;, mit dem man die enthaltenen Dateien verwalten kann. Enth&auml;lt ein Anlage-Feld Bilddateien, k&ouml;nnen diese mit dem Bild-Steuerelement von Access direkt in Formularen und Berichten angezeigt werden. Wenn man seine Tabellen zum SQL Server migrieren m&ouml;chte, wird dies jedoch zu einem Problem: Im SQL Server gibt es n&auml;mlich kein Pendant zum Anlage-Feld, sondern nur Alternativen wie beispielsweise den varbinary(max)-Datentyp. Damit k&ouml;nnen wir zwar die Dateien im bin&auml;ren Format im SQL Server speichern, aber rundherum ergeben sich einige Fragen: Wie zeige ich Bilddateien an, die in einem solchen Feld gespeichert sind? Wie gehe ich mit Anlage-Feldern um, die nicht nur eine Anlage enthalten? All dies erl&auml;utern wir in diesem und weiteren Beitr&auml;gen.<\/b><\/p>\n<p>Anlage-Felder sind flexibel einsetzbar. Grunds&auml;tzlich kann man in ihnen Dateien speichern, und zwar so viele, wie man m&ouml;chte. Der Grund daf&uuml;r ist, dass Access im Hintergrund eine eigene Tabelle f&uuml;r die einzelnen Anlagen eines Anlage-Feldes bereith&auml;lt.<\/p>\n<p>Das dies der Fall ist, werden wir sp&auml;ter sehen, wenn wir mit zwei verschachtelten Recordsets auf die einzelnen Datens&auml;tze eines Anlage-Feldes zugreifen.<\/p>\n<p>Aber man kann nicht nur einfach Dateien in Anlage-Feldern speichern. Wenn es sich bei den Dateien um Bilddateien handelt, k&ouml;nnen wir diese sogar beispielsweise im Anlage-Steuerelement oder im Bild-Steuerelement (mit wesentlich mehr Aufwand) anzeigen.<\/p>\n<p>Um die in einem Anlage-Feld enthaltenen Dateien in einem Formular zu verwalten, brauchen wir nur das Anlagefeld in den Tabellenentwurf zu ziehen. Klicken wir dieses dann an, sehen wir ein kleines Popup-Men&uuml; mit drei Befehlen, von denen die ersten beiden zum Navigieren zwischen den enthaltenen Dateien und die dritte zum &Ouml;ffnen des Dialogs zum Verwalten der enthaltenen Dateien verwendet wird (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1542_001.png\" alt=\"Anzeigen von Bildern aus einem Anlage-Feld\" width=\"549,559\" height=\"360,562\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Anzeigen von Bildern aus einem Anlage-Feld<\/span><\/b><\/p>\n<p>Wir gehen an dieser Stelle davon aus, dass wir bereits eine Beispieltabelle mit den drei Feldern <b>AnlageID <\/b>(Prim&auml;rschl&uuml;sselfeld), <b>Bezeichnung <\/b>(Textfeld) und <b>Anlagefeld <\/b>(Anlage-Feld) erstellt haben, die wir als Datensatzquelle des Formulars verwenden.<\/p>\n<h2>Anlage-Felder im SQL Server?<\/h2>\n<p>Zum Problem werden Anlage-Felder, wenn wir sie zum SQL Server migrieren wollen. Im Beitrag <b>Bilder im SQL Server mit varbinary(max)<\/b> (<b>www.access-im-unternehmen.de\/1538<\/b>) zeigen wir, wie man Bild-Dateien in einem <b>varbinary(max)<\/b>-Feld des SQL Servers speichert und wie man die Bilder daraus in einem Bild-Steuerelement in Access anzeigt.<\/p>\n<p>Im vorliegenden Artikel schauen wir uns genauer an, wie eine Tabelle mit Anlage-Feld zu einer entsprechenden SQL Server-Tabelle migriert werden kann. Dabei ist auch hier unser Ziel, ein entsprechendes <b>varbinary(max)<\/b>-Feld zu erstellen und die Inhalte unseres Anlage-Feldes automatisiert zum SQL Server zu &uuml;bertragen.<\/p>\n<p>Zuvor m&uuml;ssen wir jedoch ein wenig planen.<\/p>\n<h2>Migration mit dem SQL Server Migration-Assistant: Wie Anlage-Felder ber&uuml;cksichtigen?<\/h2>\n<p>Der SQL Server Migration Assistant ist das beste Werkzeug, wenn es um eine weitgehend automatisierte Migration der Tabellen von Access zu einer SQL Server-Datenbank geht.<\/p>\n<p>Es werden m&ouml;gliche Probleme angezeigt und es k&ouml;nnen alle Tabellen, Felder, Beziehungen, weitere Eigenschaften und auch noch die Daten migriert werden.<\/p>\n<p>Leider bietet der SQL Server Migration Assistant keine M&ouml;glichkeit, ein Feld mit dem Datentyp <b>Anlage <\/b>in ein entsprechendes Feld zu migrieren. Der Workaround des SQL Server Migration Assistant ist es, eine Meldung anzuzeigen, dass der <b>Attachment<\/b>-Datentyp nicht migriert werden kann, und stattdessen immerhin das Feld als <b>varchar(8000)<\/b>-Feld anzulegen.<\/p>\n<p>Hier haben wir nun zwei M&ouml;glichkeiten:<\/p>\n<ul>\n<li>Wir k&ouml;nnen die Situation so aufgreifen, wie sie ist, und f&uuml;r alle Anlage-Felder in der Quelldatenbank das daf&uuml;r erstellte <b>varchar(8000)<\/b>-Feld in ein <b>varbinary(max)<\/b>-Feld umwandeln und die entsprechenden Dateien in dieses Feld &uuml;bertragen.<\/li>\n<li>Oder wir lassen die Tabelle bei der Migration aus und migrieren sie komplett von Hand. Das w&uuml;rde jedoch bedeuten, dass wir auch die Beziehungen, an denen diese Tabelle beteiligt ist, nachtr&auml;glich hinzuf&uuml;gen m&uuml;ssen. Das scheint auf jeden Fall die aufwendigere Variante zu sein, vor allem deshalb, weil die Migration die &uuml;brigen Felder der Tabelle korrekt durchf&uuml;hrt.<\/li>\n<\/ul>\n<p>Au&szlig;erdem m&uuml;ssen wir noch beachten, dass ein Anlage-Feld auch immer mehr als eine Datei enthalten kann. Wie oben erw&auml;hnt, befindet sich hinter einem Anlage-Feld immer eine intern gepflegte Tabelle, die f&uuml;r jede enthaltene Datei einen eigenen Datensatz anlegt.<\/p>\n<p>Wenn wir dies korrekt im SQL Server abbilden wollen, brauchen wir also eigentlich sogar eine eigene Tabelle f&uuml;r die Dateien. <\/p>\n<p>Da es jedoch auch F&auml;lle gibt, in denen die Anzahl der enthaltenen Dateien auf eine begrenzt ist, schauen wir uns zun&auml;chst diese einfachere Methode an.<\/p>\n<p>Nochmal zusammengefasst die Ausgangssituation: Wir haben eine Migration durchgef&uuml;hrt und es fehlen nur noch die Anlage-Felder und ihre Daten, die als <b>varbinary(max)<\/b>-Felder angelegt werden sollen.<\/p>\n<p>Also lauten die Voraussetzungen:<\/p>\n<ul>\n<li>Wir haben eine Access-Tabelle mit einem Anlage-Feld.<\/li>\n<li>Wir haben diese Tabelle bereits zum SQL Server migriert, wobei das Feld mit dem Datentyp <b>varchar(8000) <\/b>angelegt wurde.<\/li>\n<\/ul>\n<p>Wir werden also zun&auml;chst eine Prozedur erstellen, der wir den Namen der Tabelle und des Feldes auf Access-Seite &uuml;bergeben sowie den Namen der Tabelle und des Feldes in der SQL Server-Datenbank.<\/p>\n<p>Diese Prozedur soll nun folgende Schritte ausf&uuml;hren:<\/p>\n<ul>\n<li>Das vorhandene Feld mit dem Datentyp <b>varchar(8000)<\/b> l&ouml;schen.<\/li>\n<li>Ein neues Feld mit dem Datentyp <b>varbinary(max)<\/b> anlegen.<\/li>\n<li>Den Inhalt des Anlage-Feldes f&uuml;r alle Datens&auml;tze der Quelltabelle in das neue <b>varbinary(max)<\/b>-Feld &uuml;bertragen.<\/li>\n<\/ul>\n<h2>Vorbereitung<\/h2>\n<p>Wir ben&ouml;tigen einen Verweis auf die Bibliothek <b>Microsoft ActiveX Data Objects 6.1 Library<\/b>, den wir &uuml;ber den <b>Verweise<\/b>-Dialog des VBA-Editors hinzuf&uuml;gen k&ouml;nnen.<\/p>\n<h2>Prozeduren zum Anlegen und &Uuml;bertragen erstellen<\/h2>\n<p>Aus Gr&uuml;nden der Wartbarkeit wollen wir die Funktion auf mehrere Routinen aufteilen. Die erste, die wir uns anschauen, soll die Voraussetzungen liefern, um &uuml;berhaupt Bilddaten in die SQL Server-Tabelle schreiben zu k&ouml;nnen.<\/p>\n<p>Zuallererst legen wir jedoch die Verbindungszeichenfolge fest, die wir f&uuml;r den Zugriff per ADODB auf die Datenbank ben&ouml;tigen. Sie sieht wie folgt aus und erfordert noch das Ersetzen der Platzhalter <b>[SERVER]<\/b> und <b>[DATABASE] <\/b>durch die bei Ihnen vorliegenden Werte:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Const cStrConnection<span style=\"color:blue;\"> As String<\/span> = \"Provider=MSOLEDBSQL;Data Source=[SERVER];Initial Catalog=[DATABASE];Integrated Security=SSPI;\"<\/pre>\n<p>Danach erstellen wir die erste Funktion namens <b>VarbinaryFeldAnlegenOderAnpassen<\/b> (siehe Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>VarbinaryFeldAnlegenOderAnpassen(cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection, strSQLTabelle<span style=\"color:blue;\"> As String<\/span>, _\r\n         strSQLFeld<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> lngErrNumber<span style=\"color:blue;\"> As Long<\/span>, <span style=\"color:blue;\">Optional<\/span> strErrDescription<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\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     <span style=\"color:blue;\">Dim <\/span>intResult<span style=\"color:blue;\"> As <\/span>VbMsgBoxResult\r\n     <span style=\"color:blue;\">Set<\/span> rst = <span style=\"color:blue;\">New<\/span> ADODB.Recordset\r\n     strSQL = \"SELECT DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS \" & _\r\n              \"WHERE TABLE_NAME = ''\" & strSQLTabelle & \"'' AND COLUMN_NAME = ''\" & strSQLFeld & \"''\"\r\n     rst.Open strSQL, cnn, adOpenStatic, adLockReadOnly\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span>rst.Fields(\"DATA_TYPE\").Value &lt;&gt; \"varbinary\" Or rst.Fields(\"CHARACTER_MAXIMUM_LENGTH\").Value &lt;&gt; -1<span style=\"color:blue;\"> Then<\/span>\r\n             intResult = <span style=\"color:blue;\">MsgBox<\/span>(\"Das Feld \" & strSQLFeld & \" ist kein varbinary(max). Soll es ge&auml;ndert werden?\", _\r\n                 vbYesNo + vbQuestion, \"Feld anpassen?\")\r\n             <span style=\"color:blue;\">If <\/span>intResult = vbYes<span style=\"color:blue;\"> Then<\/span>\r\n                 On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                 cnn.Execute \"ALTER TABLE \" & strSQLTabelle & \" DROP COLUMN \" & strSQLFeld\r\n                 cnn.Execute \"ALTER TABLE \" & strSQLTabelle & \" ADD \" & strSQLFeld & \" varbinary(max)\"\r\n                 <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> Err.Number = 0<span style=\"color:blue;\"> Then<\/span>\r\n                     lngErrNumber = Err.Number\r\n                     strErrDescription = Err.Description\r\n                     <span style=\"color:blue;\">Exit Function<\/span>\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n                 <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         intResult = <span style=\"color:blue;\">MsgBox<\/span>(\"Das Feld ''\" & strSQLFeld & \"'' ist noch nicht vorhanden. Soll es mit dem \" _\r\n             & \"Datentyp varbinarx(max) angelegt werden?\", vbYesNo, \"Feld nicht vorhanden\")\r\n         <span style=\"color:blue;\">If <\/span>intResult = vbYes<span style=\"color:blue;\"> Then<\/span>\r\n             On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n             cnn.Execute \"ALTER TABLE \" & strSQLTabelle & \" ADD \" & strSQLFeld & \" varbinary(max)\"\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> Err.Number = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 strErrDescription = Err.Description\r\n                 lngErrNumber = Err.Number\r\n                 <span style=\"color:blue;\">Exit Function<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     VarbinaryFeldAnlegenOderAnpassen = <span style=\"color:blue;\">True<\/span>\r\n     rst.Close\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Funktion zum Anlegen von varbinary(max)-Feldern oder Umwandeln von anderen Felddatentypen in varbinary(max)<\/span><\/b><\/p>\n<p>Sie erwartet die folgenden Parameter:<\/p>\n<ul>\n<li><b>cnn<\/b>: <b>ADODB.Connection<\/b>-Objekt f&uuml;r die zu verwendende Verbindung<\/li>\n<li><b>strSQLTabelle<\/b>: Name der zu verwendenden Tabelle auf dem SQL Server<\/li>\n<li><b>strSQLFeld<\/b>: Name des anzupassenden\/zu erstellenden Bildfeldes auf dem SQL Server<\/li>\n<\/ul>\n<p>Die Funktion liefert den Wert <b>True <\/b>zur&uuml;ck, wenn das Feld vorhanden ist (gegebenenfalls durch Anpassung oder Erstellung).<\/p>\n<p>Die Funktion erstellt als Erstes ein neues <b>ADODB.Recordset <\/b>und referenziert es mit der Variablen <b>rst<\/b>.<\/p>\n<p>Dann stellt es in der Variablen <b>strSQL <\/b>eine Abfrage zusammen, die in unserem Beispiel wie folgt aussieht:<\/p>\n<pre>SELECT DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ''tblBilder'' AND COLUMN_NAME = ''Bild''<\/pre>\n<p>Diese Abfrage ermittelt den Datentyp und die Anzahl Zeichen des Feldes, das noch den Datentyp <b>varchar(8000) <\/b>hat und das wir ersetzen wollen.<\/p>\n<p>Diese Abfrage &ouml;ffnen wir mit der <b>Open<\/b>-Methode des Recordsets und pr&uuml;fen in einer <b>If&#8230;Then<\/b>-Bedingung, ob &uuml;berhaupt ein entsprechender Datensatz gefunden wurde, sprich: ob das Feld &uuml;berhaupt vorhanden ist.<\/p>\n<p>Falls ja, pr&uuml;ft die zweite <b>If&#8230;Then<\/b>-Bedingung, ob der Datentyp des Feldes ungleich <b>varbinary <\/b>ist oder ob die maximale Zeichenanzahl f&uuml;r dieses Feld ungleich <b>-1 <\/b>ist (was MAX entspricht). In diesem Fall erscheint eine Meldung, die fragt, ob der Datentyp des Feldes ge&auml;ndert werden soll.<\/p>\n<p>Antwortet der Benutzer mit <b>Ja<\/b>, f&uuml;hrt die Funktion bei deaktivierter Fehlerbehandlung zwei SQL-Anweisungen aus. <\/p>\n<ul>\n<li>Die erste Anweisung l&ouml;scht das bestehende Feld mit dem angegebenen Namen.<\/li>\n<li>Die zweite f&uuml;gt das neue Feld mit dem Datentyp <b>varbinary(max) <\/b>hinzu.<\/li>\n<\/ul>\n<p>L&ouml;st dies einen Fehler aus, werden die beiden R&uuml;ckgabeparameter <b>lngErrNumber <\/b>und <b>strErrDescription <\/b>mit den entsprechenden Werten aus der <b>Err<\/b>-Klasse gef&uuml;llt und die Funktion wird verlassen.<\/p>\n<p>Es kann auch geschehen, dass das Feld, dessen Name wir mit <b>strSQLFeld <\/b>&uuml;bergeben haben, noch nicht vorhanden ist. Dann erscheint eine Meldung, die den Benutzer fragt, ob es mit den Datentyp <b>varbinary(max) <\/b>angelegt werden soll. Antwortet der Benutzer mit <b>Ja<\/b>, wird dieses Feld zur Tabelle aus <b>strSQLTabelle <\/b>hinzugef&uuml;gt. Tritt hier ein Fehler auf, verfahren wir mit den Fehlerinformationen wie oben.<\/p>\n<p>Damit haben wir bereits das ben&ouml;tigte Feld mit dem Datentyp <b>varbinary(max)<\/b> vorbereitet.<\/p>\n<h2>Kopieren der Daten von Anlagefeld zum varbinary(max)-Feld<\/h2>\n<p>Hier stellt sich die Frage, wie wir im Detail beim Kopieren vorgehen wollen. Der Prozess ist ohnehin individuell, weil jedes Bild einzeln vom Anlage-Feld in ein Byte-Array &uuml;bertragen und dann in das <b>varbinary(max)<\/b>-Feld eingetragen werden muss.<\/p>\n<p>Wir k&ouml;nnen nun verschiedene M&ouml;glichkeiten w&auml;hlen. Die erste Frage ist:<\/p>\n<ul>\n<li>Soll die Prozedur nur die Inhalte der Anlage-Felder in die entsprechenden <b>varbinary(max)<\/b>-Felder kopieren?<\/li>\n<li>Oder soll diese direkt den vollst&auml;ndige Datensatz kopieren?<\/li>\n<\/ul>\n<p>Es wird vermutlich im Laufe der Zeit mal den einen, mal den anderen Fall geben. Weiter oben haben wir bereits diskutiert, dass es vermutlich oft vorkommt, dass das vollst&auml;ndige Datenmodell bis auf die Anlage-Felder mit Tools wie dem SQL Server Migration Assistant zum SQL Server &uuml;bertragen wird.<\/p>\n<p>Wir tun uns also in den meisten F&auml;llen einen Gefallen, indem wir den Teil, der das Anlage-Feld in das <b>varbinary(max)<\/b>-Feld &uuml;bertr&auml;gt, in einer eigenen Funktion realisieren.<\/p>\n<p>Wir k&ouml;nnen dann beispielsweise die folgenden Varianten f&uuml;r aufrufende Funktionen w&auml;hlen:<\/p>\n<ul>\n<li>Eine Prozedur, die alle Datens&auml;tze der Access-Tabelle mit dem Anlage-Feld durchl&auml;uft und zun&auml;chst alle Daten au&szlig;er dem Anlage-Feld in die SQL Server-Tabelle kopiert. F&uuml;r jeden aktuellen Datensatz wird dann die oben beschriebene Funktion zum &Uuml;bertragen der Daten aus dem Anlage-Feld aufgerufen.<\/li>\n<li>Oder wir f&uuml;hren das Kopieren der einfachen Daten in einer <b>INSERT INTO<\/b>-Anweisung f&uuml;r alle Datens&auml;tze gleichzeitig durch und durchlaufen anschlie&szlig;end eine Schleife mit allen Datens&auml;tzen, wo wir die Inhalte der Anlage-Felder nachziehen.<\/li>\n<\/ul>\n<p>In beiden F&auml;llen ben&ouml;tigen wir eine eigene Prozedur, die davon ausgeht, dass der eigentliche Datensatz bereits kopiert wurde und nur noch der Inhalt der Anlage-Felder &uuml;bertragen werden muss.<\/p>\n<h2>Funktion zum &Uuml;bertragen der Anlage-Felder<\/h2>\n<p>Daher programmieren wir die Funktion namens <b>CopyAttachmentToVarBinaryMax <\/b>so, dass wir mit den Parametern die folgenden Informationen &uuml;bergeben:<\/p>\n<ul>\n<li><b>strAccessTable<\/b>: Name der verwendeten Quelltabelle in Access<\/li>\n<li><b>strAccessField<\/b>: Name des Anlage-Feldes in der Access-Tabelle<\/li>\n<li><b>strAccessPKField<\/b>: Name des Prim&auml;rschl&uuml;sselfeldes in der Access-Tabelle<\/li>\n<li><b>lngAccessPKID<\/b>: Wert des Prim&auml;rschl&uuml;sselfeldes f&uuml;r den zu &uuml;bertragenden Datensatz in der Access-Tabelle<\/li>\n<li><b>strSQLTable<\/b>: Name der Zieltabelle auf dem SQL Server<\/li>\n<li><b>strSQLField<\/b>: Name des <b>varbinary(max)<\/b>-Feldes in der Zieltabelle<\/li>\n<li><b>strSQLPKField<\/b>: Name des Prim&auml;rschl&uuml;sselfeldes der SQL Server-Tabelle<\/li>\n<li><b>lngSQLPKID<\/b>: Wert des Prim&auml;rschl&uuml;sselfeldes f&uuml;r den zu &uuml;bertragenden Datensatz in der SQL Server-Tabelle<\/li>\n<li><b>cnn<\/b>: ADODB-Verbindung<\/li>\n<li><b>strErrorMessage<\/b>: Au&szlig;erdem verwenden wir noch einen Parameter, der Informationen zu einem eventuell aufgetretenen Fehler zur&uuml;ckgibt. <\/li>\n<\/ul>\n<p>Die Funktion ist die Steuerzentrale f&uuml;r verschiedene Schritte (siehe Listing 2). Sie sorgt zun&auml;chst daf&uuml;r, dass die im Anlagefeld gespeicherte Datei auf der Festplatte gespeichert wird. Dazu nutzt sie die Funktion <b>SaveAttachmentToFile<\/b>. Das Ergebnis ist der Pfad zu dieser Datei.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>CopyAttachmentToVarBinaryMax(strAccessTable<span style=\"color:blue;\"> As String<\/span>, strAccessField<span style=\"color:blue;\"> As String<\/span>, _\r\n         strAccessPKField<span style=\"color:blue;\"> As String<\/span>, lngAccessPKID<span style=\"color:blue;\"> As Long<\/span>, strSQLTable<span style=\"color:blue;\"> As String<\/span>, strSQLField<span style=\"color:blue;\"> As String<\/span>, _\r\n         strSQLPKField<span style=\"color:blue;\"> As String<\/span>, lngSQLPKID<span style=\"color:blue;\"> As Long<\/span>, cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection, _\r\n         <span style=\"color:blue;\">Optional<\/span> strErrorMessage<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bytData()<span style=\"color:blue;\"> As Byte<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strFilepath<span style=\"color:blue;\"> As String<\/span>\r\n     \r\n     If SaveAttachmentToFile(strAccessTable, strAccessField, strAccessPKField, lngAccessPKID, strFilepath, _\r\n             strErrorMessage) = <span style=\"color:blue;\">False<\/span> Then\r\n         <span style=\"color:blue;\">Exit Function<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">If <\/span>LoadFileToByteArray(strFilepath, bytData) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             If AddByteArrayToVarBinaryMax(cnn, strSQLTable, strSQLField, strSQLPKField, lngSQLPKID, bytData, _\r\n                     strErrorMessage) = <span style=\"color:blue;\">True<\/span> Then\r\n                 CopyAttachmentToVarBinaryMax = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 CopyAttachmentToVarBinaryMax = <span style=\"color:blue;\">False<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Funktion zum Kopieren von Attachment-Inhalten in ein varbinary(max)-Feld<\/span><\/b><\/p>\n<p>War der Aufruf dieser Funktion erfolgreich, folgt die n&auml;chste Funktion, mit der wir den Inhalt der Datei in ein <b>Byte<\/b>-Array einlesen. Diese Funktion hei&szlig;t <b>LoadFileToByteArray<\/b>. Sie liefert mit dem Parameter <b>bytData <\/b>das <b>Byte<\/b>-Array zur&uuml;ck.<\/p>\n<p>War auch dies erfolgreich, folgt der n&auml;chste Funktionsaufruf, diesmal f&uuml;r die Funktion <b>AddByteArrayToVarBinaryMax<\/b>. Diese soll schlie&szlig;lich das <b>Byte<\/b>-Array in das angegebene Feld der entsprechenden Tabelle eintragen.<\/p>\n<h2>Funktion zum Speichern einer Anlage im Dateisystem<\/h2>\n<p>Die Funktion <b>SaveAttachmentToFile <\/b>(siehe Listing 3) erwartet die dazu notwendigen Parameter, hier <b>strAccessTable<\/b>, <b>strAccessField<\/b>, <b>strAccessPKField <\/b>und <b>lngAccessPKID<\/b>. <\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>SaveAttachmentToFile(strAccessTable<span style=\"color:blue;\"> As String<\/span>, strAccessField<span style=\"color:blue;\"> As String<\/span>, strAccessPKField<span style=\"color:blue;\"> As <\/span>_\r\n         String, lngAccessPKID<span style=\"color:blue;\"> As Long<\/span>, strFilepath<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> strErrorMessage<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstAttach<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>DAO.Field2\r\n     <span style=\"color:blue;\">Dim <\/span>strFilename<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strFileExtension<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     strSQL = \"SELECT \" & strAccessField & \" FROM \" & strAccessTable & \" WHERE \" & strAccessPKField & \" = \" _\r\n         & lngAccessPKID\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(strSQL, dbOpenDynaset)\r\n     \r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> rstAttach = rst.Fields(strAccessField).Value\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rstAttach.EOF<span style=\"color:blue;\"> Then<\/span>\r\n             Select Case rstAttach.RecordCount\r\n                 <span style=\"color:blue;\">Case <\/span>1\r\n                     <span style=\"color:blue;\">Set<\/span> fld = rstAttach.Fields(\"FileData\")\r\n                     strFilename = rstAttach.Fields(\"FileName\")\r\n                     strFileExtension = <span style=\"color:blue;\">Mid<\/span>(strFilename, <span style=\"color:blue;\">InStrRev<\/span>(strFilename, \".\"))\r\n                     strFilepath = CurrentProject.Path & \"\\temp\" & strFileExtension\r\n                     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                     Kill strFilepath\r\n                     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n                     fld.SaveToFile strFilepath\r\n                     SaveAttachmentToFile = <span style=\"color:blue;\">True<\/span>\r\n                 <span style=\"color:blue;\">Case Else<\/span>\r\n                     strErrorMessage = \"Mehr als ein Anhang im Datensatz vorhanden.\"\r\n         GoTo Exit_Function\r\n             <span style=\"color:blue;\">End Select<\/span>\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             strErrorMessage = \"Kein Anhang im Datensatz vorhanden.\"\r\n         GoTo Exit_Function\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         strErrorMessage = \"Kein Datensatz gefunden.\"\r\n         GoTo Exit_Function\r\n     <span style=\"color:blue;\">End If<\/span>\r\nExit_Function:\r\n     rstAttach.Close\r\n     <span style=\"color:blue;\">Set<\/span> rstAttach = Nothing\r\n     rst.Close\r\n     <span style=\"color:blue;\">Set<\/span> rst = Nothing\r\n     <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Funktion zum Speichern einer Datei aus einem Anlagefeld in eine Datei auf der Festplatte<\/span><\/b><\/p>\n<p>Die folgenden beiden Parameter sind R&uuml;ckgabeparameter:<\/p>\n<ul>\n<li><b>strFilepath<\/b>: Liefert den Pfad der erstellten Datei zur&uuml;ck.<\/li>\n<li><b>strErrorMessage<\/b>: Liefert eine Fehlerbeschreibung, falls das Erstellen der Datei nicht funktioniert.<\/li>\n<\/ul>\n<p>Die Funktion stellt in <b>strSQL<\/b> eine Abfrage zusammen, die das Anlagefeld der &uuml;bergebenen Tabelle f&uuml;r den angegebenen Prim&auml;rschl&uuml;sselwert zur&uuml;ckliefern soll. Dieses &ouml;ffnet die Funktion per <b>OpenRecordset<\/b>.<\/p>\n<p>Danach pr&uuml;ft sie, ob das Recordset nicht leer ist und weist dann dem Recordset <b>rstAttach <\/b>das Feld mit dem Anlagefeld hinzu.<\/p>\n<p>Dieses enth&auml;lt eine intern gespeicherte Tabelle mit den einzelnen Anlagen. Um auf das enthaltene Recordset zuzugreifen, m&uuml;ssen wir die <b>Value<\/b>-Eigenschaft verwenden.<\/p>\n<p>Nun pr&uuml;fen wir, ob das Recordset <b>rstAttach <\/b>nicht leer ist. Ist das nicht der Fall, werten wir die Datensatzanzahl in einer <b>Select Case<\/b>-Anweisung aus.<\/p>\n<p>Im Falle genau eines Datensatzes referenzieren wir das im Recordset enthaltene Feld <b>FileData <\/b>mit der Variablen <b>fld<\/b>. Au&szlig;erdem ermitteln wir den Dateinamen aus dem Feld <b>FileName<\/b>. Aus diesem extrahieren wir mit der <b>Mid<\/b>&#8211; und der <b>InStrRev<\/b>-Funktion die Dateiendung und speichern sie in der Variablen <b>strFileExtension<\/b>.<\/p>\n<p>Die Namen dieser Felder k&ouml;nnen wir aus Bild 2 entnehmen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1542_004.png\" alt=\"Quellfelder f&uuml;r die Dateien-Tabelle\" width=\"424,5589\" height=\"238,9965\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Quellfelder f&uuml;r die Dateien-Tabelle<\/span><\/b><\/p>\n<p>Wir stellen den Pfad, unter dem die Datei gespeichert werden soll, aus dem aktuellen Datenbankverzeichnis (<b>CurrentProject.Path<\/b>), der Zeichenkette <b>\\temp <\/b>und der Dateiendung zusammen.<\/p>\n<p>Danach versuchen wir, eine eventuell bereits vorhandene Datei gleichen Namens bei deaktiverter Fehlerbehandlung zu l&ouml;schen. Ist das erledigt, k&ouml;nnen wir die Datei mit der <b>SaveToFile<\/b>-Methode unter dem mit <b>strFilepath <\/b>angegebenen Pfad speichern. In diesem Fall stellen wir das Funktionsergebnis auf <b>True <\/b>ein.<\/p>\n<p>Wenn das Recordset mehr als eine Anlage enth&auml;lt, verlassen wir die Funktion und geben eine entsprechende Meldung zur&uuml;ck.<\/p>\n<p>Es kann auch sein, dass das Anlagefeld gar keine Daten enth&auml;lt, was wir ebenfalls mit einer entsprechenden Meldung adressieren.<\/p>\n<p>Zuletzt schlie&szlig;en wir alle Recordsets wieder und leeren die Objektvariablen.<\/p>\n<h2>Byte-Array aus Datei generieren<\/h2>\n<p>Die n&auml;chste Funktion hei&szlig;t <b>LoadFileToByteArray<\/b> (siehe Listing 4). Sie erwartet die folgenden Parameter:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>LoadFileToByteArray(strFilepath<span style=\"color:blue;\"> As String<\/span>, bytData()<span style=\"color:blue;\"> As Byte<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objStream<span style=\"color:blue;\"> As <\/span>ADODB.Stream\r\n     <span style=\"color:blue;\">Set<\/span> objStream = <span style=\"color:blue;\">New<\/span> ADODB.Stream\r\n     <span style=\"color:blue;\">With<\/span> objStream\r\n         .Type = adTypeBinary\r\n         .Open\r\n         .LoadFromFile strFilepath\r\n         bytData = .Read\r\n         .Close\r\n         LoadFileToByteArray = <span style=\"color:blue;\">True<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Funktion zum Erzeugen eines Byte-Arrays aus einer gespeicherten Datei<\/span><\/b><\/p>\n<ul>\n<li><b>strFilepath<\/b>: Erwartet den Pfad der Datei, die in ein <b>Byte<\/b>-Array eingelesen werden soll.<\/li>\n<li><b>bytData()<\/b>: R&uuml;ckgabeparameter mit dem Byte-Array auf Basis der Datei<\/li>\n<\/ul>\n<p>Die Funktion deklariert und erstellt ein <b>ADODB.Stream<\/b>-Objekt in der Variablen <b>objStream<\/b>.<\/p>\n<p>Dieses f&uuml;llen wir mit der <b>LoadFromFile<\/b>-Methode mit dem Inhalt der Datei aus <b>strFilePath<\/b>. Dieses k&ouml;nnen wir dem Byte-Array <b>bytData <\/b>&uuml;ber die <b>Read<\/b>-Funktion zuweisen.<\/p>\n<h2>Byte-Array in varbinary(max)-Feld schreiben<\/h2>\n<p>Die n&auml;chste Funktion namens <b>AddByteArrayToVarBinaryMax <\/b>schreibt schlie&szlig;lich den Inhalt des Byte-Arrays in das <b>varbinary(max)<\/b>-Feld der SQL Server-Tabelle (siehe Listing 5).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddByteArrayToVarBinaryMax(cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection, strSQLTable<span style=\"color:blue;\"> As String<\/span>, strSQLField<span style=\"color:blue;\"> As String<\/span>, _\r\n         strSQLPKField<span style=\"color:blue;\"> As String<\/span>, lngSQLPKID<span style=\"color:blue;\"> As Long<\/span>, bytData()<span style=\"color:blue;\"> As Byte<\/span>, <span style=\"color:blue;\">Optional<\/span> strErrorMessage<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>cmd<span style=\"color:blue;\"> As <\/span>ADODB.Command\r\n     <span style=\"color:blue;\">Dim <\/span>lngRecordsAffected<span style=\"color:blue;\"> As Long<\/span>\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>prm<span style=\"color:blue;\"> As <\/span>ADODB.Parameter\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> cmd = <span style=\"color:blue;\">New<\/span> ADODB.Command\r\n     <span style=\"color:blue;\">Set<\/span> rst = <span style=\"color:blue;\">New<\/span> ADODB.Recordset\r\n     strSQL = \"SELECT \" & strSQLField & \" FROM \" & strSQLTable & \" WHERE \" & strSQLPKField & \" = \" & lngSQLPKID\r\n     rst.Open strSQL, cnn, adOpenStatic, adLockReadOnly\r\n     <span style=\"color:blue;\">If <\/span>rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n         strErrorMessage = \"Der Datensatz mit dem Wert \" & lngSQLPKID & \" im Feld \" & strSQLPKField _\r\n             & \" existiert nicht.\"\r\n         <span style=\"color:blue;\">Exit Function<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">With<\/span> cmd\r\n             .ActiveConnection = cnn\r\n             .CommandType = adCmdText\r\n             .CommandText = \"UPDATE \" & strSQLTable & \" SET \" & strSQLField & \" = ? WHERE \" & strSQLPKField & \" = \" _\r\n                 & lngSQLPKID\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> IsEmpty(bytData)<span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">Set<\/span> prm = .CreateParameter(\"img\", adLongVarBinary, adParamInput, <span style=\"color:blue;\">UBound<\/span>(bytData) - _\r\n                     <span style=\"color:blue;\">LBound<\/span>(bytData) + 1, bytData)\r\n                 .Parameters.Append prm\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 strErrorMessage = \"Fehler: Die Anlage enth&auml;lt keine Daten und kann nicht gespeichert werden.\"\r\n                 GoTo Exit_Function\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             .Execute lngRecordsAffected\r\n         End <span style=\"color:blue;\">With<\/span>\r\n         <span style=\"color:blue;\">If <\/span>lngRecordsAffected = 0<span style=\"color:blue;\"> Then<\/span>\r\n             strErrorMessage = \"Es wurde keine Anlage hinzugef&uuml;gt.\"\r\n             GoTo Exit_Function\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             AddByteArrayToVarBinaryMax = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\nExit_Function:\r\n     <span style=\"color:blue;\">Set<\/span> cmd = Nothing\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Funktion zum Speichern des Inhalts des Byte-Arrays im varbinary(max)-Feld<\/span><\/b><\/p>\n<p>Die Funktion erwartet die folgenden Parameter:<\/p>\n<ul>\n<li><b>cnn<\/b>: Verbindungszeichenfolge zur SQL Server-Datenbank<\/li>\n<li><b>strSQLTable<\/b>: Tabelle auf dem SQL Server mit dem <b>varbinary(max)<\/b>-Feld<\/li>\n<li><b>strSQLField<\/b>: Bezeichnung des <b>varbinary(max)<\/b>-Feldes<\/li>\n<li><b>strSQLPKField<\/b>: Bezeichnung des Prim&auml;rsch&uuml;sselfeldes<\/li>\n<li><b>lngSQLPKID<\/b>: Wert des Prim&auml;rschl&uuml;sselfeldes f&uuml;r den anzupassenden Datensatz<\/li>\n<li><b>bytData()<\/b>: Byte-Array mit dem zu speichernden Inhalt<\/li>\n<li><b>strErrorMessage<\/b>: R&uuml;ckgabeparameter f&uuml;r eventuelle Fehlermeldungen<\/li>\n<\/ul>\n<p>Die Funktion deklariert ein neues <b>Command<\/b>-Objekt und ein <b>Recordset<\/b>-Objekt. Sie definiert eine SQL-Anweisung, die das <b>varbinary(max)<\/b>-Feld der SQL Server-Tabelle f&uuml;r den angegebenen Datensatz zur&uuml;ckliefert.<\/p>\n<p>Diese wird als neues Recordset ge&ouml;ffnet und auf das Vorhandensein mindestens eines Datensatzes gepr&uuml;ft.<\/p>\n<p>Liegt kein Datensatz vor, wird die Funktion mit der R&uuml;ckgabe einer entsprechenden Fehlermeldung beendet. Anderenfalls erstellt sie ein <b>Command<\/b>-Objekt in der Variablen <b>cmd <\/b>und stellt die Verbindungszeichenfolge auf den Parameter <b>cnn <\/b>ein. Der <b>CommandType <\/b>wird auf <b>acCmdText <\/b>eingestellt.<\/p>\n<p>Als <b>CommandText<\/b> stellen wir eine Abfrage ein, die einen Parameter verwendet, der durch das Fragezeichen (?) gekennzeichnet wird. Wenn der Parameter <b>bytData <\/b>nicht leer ist, erstellen wir mit der <b>CreateParameter<\/b>-Methode einen Parameter in der Variablen <b>prm <\/b>und geben dabei als Name den Wert <b>img<\/b>, als Datentyp <b>adLongVarBinary<\/b>, als Richtung <b>adParamInput<\/b>, als Size die Gr&ouml;&szlig;e des Byte-Arrays und schlie&szlig;lich den Verweis auf das Array selbst.<\/p>\n<p>Diesen Parameter h&auml;ngen wir nun an die <b>Parameters<\/b>-Auflistung des <b>Command<\/b>-Objekts an.<\/p>\n<p>Schlie&szlig;lich f&uuml;hren wir das <b>Command<\/b>-Objekt mit der <b>Execute<\/b>-Methode aus und erwarten die Anzahl der betroffenen Datens&auml;tze mit dem R&uuml;ckgabeparameter <b>lngRecordsAffected<\/b>.<\/p>\n<p>Liefert dies den Wert <b>0<\/b>, wurden keine Datens&auml;tze ge&auml;ndert und wir schicken eine entsprechende Fehlerbeschreibung zur&uuml;ck. Anderenfalls erh&auml;lt die Funktion den Wert <b>True <\/b>als R&uuml;ckgabewert.<\/p>\n<h2>Aufrufen der Funktion zum Kopieren von Anlagen<\/h2>\n<p>Einen Beispielaufruf f&uuml;r diese Funktion zeigen wir in Listing 6. Sie erstellt eine <b>Database<\/b>-Variable f&uuml;r die aktuelle Datenbank sowie eine <b>ADODB.Connection <\/b>f&uuml;r die SQL Server-Datenbank.  Letztere wird direkt ge&ouml;ffnet, Erstere dient zum &Ouml;ffnen eines Recordsets mit der Tabelle, deren Anlagen zum SQL Server &uuml;bertragen werden sollen.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Test_BildAusAccessNachSQLKopieren()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\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>strErrorMessage<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>bolKopiert<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n     cnn.Open cStrConnection\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblBilder\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         bolKopiert = CopyAttachmentToVarBinaryMax(\"tblBilder\", \"Bild\", \"BildID\", rst!BildID, \"tblBilder\", \"Bild\", _\r\n             \"BildID\", rst!BildID, cnn, strErrorMessage)\r\n         <span style=\"color:blue;\">If <\/span>bolKopiert = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Datensatz \" & rst!BildID & \" nicht kopiert.\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> & strErrorMessage, _\r\n                 <span style=\"color:blue;\">vbCr<\/span>itical + vbOKOnly, \"Fehler beim Kopieren\"\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Datensatz \" & rst!BildID & \" erfolgreich kopiert.\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> cnn Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span>cnn.State = adStateOpen<span style=\"color:blue;\"> Then<\/span> cnn.Close\r\n         <span style=\"color:blue;\">Set<\/span> cnn = Nothing\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Prozedur zum Aufrufen der Funktion zum Kopieren von Anlagen<\/span><\/b><\/p>\n<p>In einer <b>Do While<\/b>-Schleife durchl&auml;uft die Prozedur alle Datens&auml;tze des Recordsets und ruft dabei jeweils die Funktion <b>CopyAttachmentToVarBinaryMax <\/b>auf.<\/p>\n<p>Dabei &uuml;bergibt sie die entsprechenden Namen der Tabellen, Prim&auml;rschl&uuml;sselfelder und Anlage-Felder auf Access- und auf SQL Server-Seite und nimmt mit dem R&uuml;ckgabeparameter <b>strErrorMessage <\/b>eventuelle Fehlermeldungen entgegen. Das Ergebnis landet in der Variablen <b>bolKopiert<\/b>. Hat diese den Wert <b>False<\/b>, gibt ein Meldungsfenster die zur&uuml;ckgelieferte Fehlermeldung aus. Auf diese Weise werden alle Datens&auml;tze des Recordsets abgearbeitet.<\/p>\n<p>Dies w&auml;re die Vorgehensweise f&uuml;r den Fall, dass wir zuvor eine Migration mit dem SQL Server Migration Assistant durchgef&uuml;hrt h&auml;tten und das Anlage-Feld als einziges noch nicht migriert worden w&auml;re.<\/p>\n<p>Sollte dieses Feld beispielsweise Bilder enthalten, k&ouml;nnte man diese wie im Beitrag <b>Bilder im SQL Server mit varbinary(max) <\/b>(<b>www.access-im-unternehmen.de\/1538<\/b>) beschrieben in einem Access-Formular anzeigen.<\/p>\n<h2>Vorgehensweise f&uuml;r den Fall, dass die Tabelle vorhanden, aber noch leer ist<\/h2>\n<p>Es kann auch sein, dass die zu migrierende Tabelle bereits angelegt wurde, aber die Daten noch nicht migriert wurden. Dann k&ouml;nnen wir das Migrieren der Daten und das &Uuml;bertragen der Inhalte der Anlagefelder in einem Zug erledigen. Wie das gelingt, zeigen wir in der Prozedur <b>DatensatzUndAnlageAusAccessNachSQLKopieren<\/b> (siehe Listing 7).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>DatensatzUndAnlageAusAccessNachSQLKopieren()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\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>strErrorMessage<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstResult<span style=\"color:blue;\"> As <\/span>ADODB.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>bolKopiert<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>cmd<span style=\"color:blue;\"> As <\/span>ADODB.Command\r\n     <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n     cnn.Open cStrConnection\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblBilder\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         strSQL = \"INSERT INTO tblBilder(Bezeichnung) OUTPUT INSERTED.BildID  VALUES(''\" & rst!Bezeichnung & \"'');\"\r\n         <span style=\"color:blue;\">Set<\/span> cmd = <span style=\"color:blue;\">New<\/span> ADODB.Command\r\n         cmd.ActiveConnection = cnn\r\n         cmd.CommandText = strSQL\r\n         cmd.CommandType = adCmdText\r\n         <span style=\"color:blue;\">Set<\/span> rstResult = cmd.Execute()\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rstResult.EOF<span style=\"color:blue;\"> Then<\/span>\r\n             lngID = rstResult!BildID\r\n             bolKopiert = CopyAttachmentToVarBinaryMax(\"tblBilder\", \"Bild\", \"BildID\", rst!BildID, \"tblBilder\", _\r\n                 \"Bild\", \"BildID\", lngID, cnn, strErrorMessage)\r\n             <span style=\"color:blue;\">If <\/span>bolKopiert = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">MsgBox<\/span> \"Datensatz \" & rst!BildID & \" nicht kopiert.\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> & strErrorMessage, _\r\n                     <span style=\"color:blue;\">vbCr<\/span>itical + vbOKOnly, \"Fehler beim Kopieren\"\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 <span style=\"color:blue;\">MsgBox<\/span> \"Datensatz \" & rst!BildID & \" erfolgreich kopiert.\"\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> cnn Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span>cnn.State = adStateOpen<span style=\"color:blue;\"> Then<\/span> cnn.Close\r\n         <span style=\"color:blue;\">Set<\/span> cnn = Nothing\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Prozedur zum Aufrufen der Funktion zum Kopieren von vollst&auml;ndigen Datens&auml;tzen mit Anlagen<\/span><\/b><\/p>\n<p>Hier durchlaufen wir das Recordset mit den Daten der Access-Datenbank in einer <b>Do While<\/b>-Schleife. Im Unterschied zu dem vorherigen Beispiel, wo wir einfach nur die Anlagen f&uuml;r die bestehenden Datens&auml;tze in die bereits kopierten Datens&auml;tze im SQL Server einf&uuml;gen, wollen wir nun die vollst&auml;ndigen Datens&auml;tze kopieren. Die erste Herausforderung hierbei ist: Wie erhalten wir die ID des hinzuf&uuml;gten Datensatzes, damit wir die Anlage in das <b>varbinary(max)<\/b>-Feld des richtigen Datensatzes hinzuf&uuml;gen? Dabei gehen wir davon aus, dass die SQL Server-Tabelle ebenfalls einen Autowert f&uuml;r das Prim&auml;rschl&uuml;sselfeld nutzt. Dazu nutzen wir eine spezielle <b>INSERT INTO<\/b>-Anweisung, die gleichzeitig den Wert des Feldes <b>BildID <\/b>f&uuml;r den hinzugef&uuml;gten Datensatz zur&uuml;ckliefert, zum Beispiel:<\/p>\n<pre>INSERT INTO tblBilder(Bezeichnung) OUTPUT INSERTED.BildID  VALUES(''Beispiel'');<\/pre>\n<p>Das Ergebnis des <b>Command<\/b>-Objekts schreiben wir in ein <b>ADODB.Recordset<\/b>-Objekt, aus dem wir danach den neuen Prim&auml;rschl&uuml;sselwert auslesen k&ouml;nnen.<\/p>\n<p>Ist das Ergebnisrecordset <b>rstResult<\/b> nicht leer, wurde der Datensatz offensichtlich erfolgreich angelegt. Dann k&ouml;nnen wir, wie im vorherigen Beispiel, die &uuml;brigen Schritte zum &Uuml;bertragen des Inhalts des Anlagefeldes durchf&uuml;hren.<\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>In diesem Beitrag haben wir eine L&ouml;sung vorgestellt, mit der Sie die Inhalte von Anlagefeldern in <b>varbinary(max)<\/b>-Felder im SQL Server &uuml;bertragen k&ouml;nnen.<\/p>\n<p>Dabei sind wir davon ausgegangen, dass die eigentliche Tabelle bereits zuvor migriert wurde, beispielsweise mit dem SQL Server Migration Assistant.<\/p>\n<p>Das Anlagefeld wird zwar ebenfalls migriert, allerdings nur als Feld mit dem Datentyp <b>varchar(8000) <\/b>und es wird lediglich mit dem Dateinamen der im Anlagefeld enthaltenen Datei gef&uuml;llt.<\/p>\n<p>Die erste Prozedur, die wir in diesem Beitrag beschrieben haben, pr&uuml;ft, ob das f&uuml;r die Anlagen zu verwendende Feld bereits vorhanden ist oder nicht. Im ersteren Fall wird es auf den Datentyp <b>varbinary(max) <\/b>eingestellt, sofern dies noch nicht der Fall ist. Wenn das Feld noch gar nicht vorhanden ist, wird es mit dem Datentyp <b>varbinary(max) <\/b>angelegt.<\/p>\n<p>Danach zeigen wir, wie wir den Inhalt des Anlagefeldes in eine Datei schreiben, diese Datei in ein Byte-Array einlesen und dieses schlie&szlig;lich in das <b>varbinary(max)<\/b>-Feld schreiben.<\/p>\n<p>In einem weiteren Beitrag namens <b>Anlagefelder mit mehreren Dateien zum SQL Server migrieren <\/b>(<b>www.access-im-unternehmen.de\/1546<\/b>) zeigen wir, wie wir mit Anlagefeldern umgehen k&ouml;nnen, die mehr als eine Datei pro Datensatz enthalten. Im vorliegenden Beitrag haben wir lediglich beschreiben, wie das mit einer einzelnen Datei funktioniert.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>AttachmentZumSQLServerMigrieren.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/EB4E7DAD-7863-44B9-99EA-F1B88DC7EB3F\/aiu_1542.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Anlage-Felder erlauben es seit Access 2010, Bilder und andere Dateien direkt in -Access-Tabellen zu speichern. Sie bieten ein praktisches Popup-Men&uuml;, mit dem man die enthaltenen Dateien verwalten kann. Enth&auml;lt ein Anlage-Feld Bilddateien, k&ouml;nnen diese mit dem Bild-Steuerelement von Access direkt in Formularen und Berichten angezeigt werden. Wenn man seine Tabellen zum SQL Server migrieren m&ouml;chte, wird dies jedoch zu einem Problem: Im SQL Server gibt es n&auml;mlich kein Pendant zum Anlage-Feld, sondern nur Alternativen wie beispielsweise den varbinary(max)-Datentyp. Damit k&ouml;nnen wir zwar die Dateien im bin&auml;ren Format im SQL Server speichern, aber rundherum ergeben sich einige Fragen: Wie zeige ich Bilddateien an, die in einem solchen Feld gespeichert sind? Wie gehe ich mit Anlage-Feldern um, die nicht nur eine Anlage enthalten? All dies erl&auml;utern wir in diesem und weiteren Beitr&auml;gen.<\/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":[662025,66032025,44000022],"tags":[],"class_list":["post-55001542","post","type-post","status-publish","format-standard","hentry","category-662025","category-66032025","category-SQL_Server_und_Co"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Anlage-Feld zum SQL Server migrieren - 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\/AnlageFeld_zum_SQL_Server_migrieren\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Anlage-Feld zum SQL Server migrieren\" \/>\n<meta property=\"og:description\" content=\"Anlage-Felder erlauben es seit Access 2010, Bilder und andere Dateien direkt in -Access-Tabellen zu speichern. Sie bieten ein praktisches Popup-Men&uuml;, mit dem man die enthaltenen Dateien verwalten kann. Enth&auml;lt ein Anlage-Feld Bilddateien, k&ouml;nnen diese mit dem Bild-Steuerelement von Access direkt in Formularen und Berichten angezeigt werden. Wenn man seine Tabellen zum SQL Server migrieren m&ouml;chte, wird dies jedoch zu einem Problem: Im SQL Server gibt es n&auml;mlich kein Pendant zum Anlage-Feld, sondern nur Alternativen wie beispielsweise den varbinary(max)-Datentyp. Damit k&ouml;nnen wir zwar die Dateien im bin&auml;ren Format im SQL Server speichern, aber rundherum ergeben sich einige Fragen: Wie zeige ich Bilddateien an, die in einem solchen Feld gespeichert sind? Wie gehe ich mit Anlage-Feldern um, die nicht nur eine Anlage enthalten? All dies erl&auml;utern wir in diesem und weiteren Beitr&auml;gen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2025-05-07T12:08:13+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg02.met.vgwort.de\/na\/10edda9852994c5f98780f5748e33207\" \/>\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=\"23\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Anlage-Feld zum SQL Server migrieren\",\"datePublished\":\"2025-05-07T12:08:13+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/\"},\"wordCount\":3555,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/10edda9852994c5f98780f5748e33207\",\"articleSection\":[\"2025\",\"3\\\/2025\",\"SQL Server und Co.\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/\",\"name\":\"Anlage-Feld zum SQL Server migrieren - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/10edda9852994c5f98780f5748e33207\",\"datePublished\":\"2025-05-07T12:08:13+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/10edda9852994c5f98780f5748e33207\",\"contentUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/10edda9852994c5f98780f5748e33207\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/AnlageFeld_zum_SQL_Server_migrieren\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Anlage-Feld zum SQL Server migrieren\"}]},{\"@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":"Anlage-Feld zum SQL Server migrieren - 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\/AnlageFeld_zum_SQL_Server_migrieren\/","og_locale":"de_DE","og_type":"article","og_title":"Anlage-Feld zum SQL Server migrieren","og_description":"Anlage-Felder erlauben es seit Access 2010, Bilder und andere Dateien direkt in -Access-Tabellen zu speichern. Sie bieten ein praktisches Popup-Men&uuml;, mit dem man die enthaltenen Dateien verwalten kann. Enth&auml;lt ein Anlage-Feld Bilddateien, k&ouml;nnen diese mit dem Bild-Steuerelement von Access direkt in Formularen und Berichten angezeigt werden. Wenn man seine Tabellen zum SQL Server migrieren m&ouml;chte, wird dies jedoch zu einem Problem: Im SQL Server gibt es n&auml;mlich kein Pendant zum Anlage-Feld, sondern nur Alternativen wie beispielsweise den varbinary(max)-Datentyp. Damit k&ouml;nnen wir zwar die Dateien im bin&auml;ren Format im SQL Server speichern, aber rundherum ergeben sich einige Fragen: Wie zeige ich Bilddateien an, die in einem solchen Feld gespeichert sind? Wie gehe ich mit Anlage-Feldern um, die nicht nur eine Anlage enthalten? All dies erl&auml;utern wir in diesem und weiteren Beitr&auml;gen.","og_url":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/","og_site_name":"Access im Unternehmen","article_published_time":"2025-05-07T12:08:13+00:00","og_image":[{"url":"http:\/\/vg02.met.vgwort.de\/na\/10edda9852994c5f98780f5748e33207","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"23\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Anlage-Feld zum SQL Server migrieren","datePublished":"2025-05-07T12:08:13+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/"},"wordCount":3555,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/#primaryimage"},"thumbnailUrl":"http:\/\/vg02.met.vgwort.de\/na\/10edda9852994c5f98780f5748e33207","articleSection":["2025","3\/2025","SQL Server und Co."],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/","url":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/","name":"Anlage-Feld zum SQL Server migrieren - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/#primaryimage"},"thumbnailUrl":"http:\/\/vg02.met.vgwort.de\/na\/10edda9852994c5f98780f5748e33207","datePublished":"2025-05-07T12:08:13+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/#primaryimage","url":"http:\/\/vg02.met.vgwort.de\/na\/10edda9852994c5f98780f5748e33207","contentUrl":"http:\/\/vg02.met.vgwort.de\/na\/10edda9852994c5f98780f5748e33207"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/AnlageFeld_zum_SQL_Server_migrieren\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Anlage-Feld zum SQL Server migrieren"}]},{"@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\/55001542","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=55001542"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001542\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001542"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001542"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}