{"id":55001546,"date":"2025-06-01T00:00:00","date_gmt":"2025-05-07T12:08:50","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1546"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/","title":{"rendered":"Anlagefelder mit mehreren Dateien zum SQL Server"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg02.met.vgwort.de\/na\/6ae36d3b4a8048ce8d2c352685ad10ab\" width=\"1\" height=\"1\" alt=\"\"><b>Im Beitrag &#8222;Anlage-Feld zum SQL Server migrieren&#8220; (www.access-im-unternehmen.de\/1542) haben wir gezeigt, wie Inhalte von Anlagefeldern einer Access-Datenbank in ein varbinary(max)-Feld einer SQL Server-Datenbank &uuml;bertragen werden k&ouml;nnen. Dort sind wir davon ausgegangen, dass jedes Anlagefeld immer nur eine Datei enth&auml;lt, was in vielen F&auml;llen ausreichend ist. Was aber, wenn der Entwickler das Anlagefeld f&uuml;r mehrere Dateien vorgesehen hat &#8211; beispielsweise, um ein oder mehrere Produktbilder zu einem Produkt zu speichern? In diesem Fall m&uuml;ssen wir umdenken, denn wir k&ouml;nnen optimalerweise immer nur eine Datei in einem varbinary(max)-Feld speichern. Zum Speichern mehrerer Dateien m&uuml;ssen wir uns also einen Workaround &uuml;berlegen. Wie dieser aussieht, schauen wir uns im vorliegenden Beitrag an.<\/b><\/p>\n<h2>Anlagefelder mit einem oder mehreren Dateien<\/h2>\n<p>Anlagefelder speichern ihre Anlagen in einer internen Tabelle, die von au&szlig;en erst einmal nicht sichtbar ist. Deshalb ist es auch m&ouml;glich, dass f&uuml;r einen einzelnen Datensatz mehr als eine Anlage hinterlegt werden kann. <\/p>\n<p>Im Beispiel verwenden wir die Tabelle <b>tblProdukte<\/b>, die in der Entwurfsansicht wie in Bild 1 aussieht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1546_001.png\" alt=\"Tabelle zum Speichern von Produkten mit Bildern\" width=\"549,559\" height=\"156,3318\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Tabelle zum Speichern von Produkten mit Bildern<\/span><\/b><\/p>\n<p>In der Datenblattansicht haben wir der Tabelle drei Bilder zum Anlagefeld hinzugef&uuml;gt (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1546_002.png\" alt=\"Tabelle mit mehreren Anlagen\" width=\"549,559\" height=\"372,6532\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Tabelle mit mehreren Anlagen<\/span><\/b><\/p>\n<p>Dass es in einem Anlagefeld ein Objekt wie eine Tabelle geben muss, sehen wir, wenn wir eine Tabelle mit einem Anlagefeld in eine neue, leere Abfrage ziehen. Hier f&uuml;gen wir einmal alle Felder der Tabelle einschlie&szlig;lich der Felder des Anlagefeldes zum Entwurfsraster hinzu (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1546_003.png\" alt=\"Die Untertabelle in einem Anlagefeld\" width=\"649,559\" height=\"386,4093\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Die Untertabelle in einem Anlagefeld<\/span><\/b><\/p>\n<p>Wechseln wir hier in die Datenblattansicht, sehen wir, dass die Idee, dass wir es hier mit einer internen Untertabelle zu tun haben, nicht allzu abwegig ist. Aus einem Datensatz werden nun direkt drei Datens&auml;tze, was sonst nur geschieht, wenn wir eine verkn&uuml;pfte Tabelle mit in den Abfrageentwurf ziehen (siehe Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1546_004.png\" alt=\"Die Felder eines Anlagefeldes in der Datenblattansicht\" width=\"649,559\" height=\"164,2351\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Die Felder eines Anlagefeldes in der Datenblattansicht<\/span><\/b><\/p>\n<h2>Anlagen mit mehreren Dateien zum SQL Server migrieren<\/h2>\n<p>Betrachten wir nun die Aufgabe, die Inhalte einer solchen Tabelle in eine SQL Server-Datenbank zu &uuml;bertragen, sehen wir erst einmal kein derartiges Konstrukt, indem wir mehrere Datens&auml;tze pro Feld speichern k&ouml;nnten. Letztlich ist das, was wir hier abgebildet sehen, nichts anderes als zwei Tabellen, die per 1:n-Beziehung miteinander verkn&uuml;pft sind. Und das l&auml;sst sich wiederum auch im SQL Server abbilden &#8211; wenn auch mit Unterst&uuml;tzung durch eine weitere Tabelle.<\/p>\n<p>Wir erstellen also im SQL Server zwei Tabellen, um die Daten dieser einen Tabelle mit Anlagefeld abzubilden. Diese sehen wie folgt aus:<\/p>\n<ul>\n<li><b>tblProdukte<\/b>: <b>ProduktID <\/b>(Prim&auml;rsch&uuml;sselfeld), <b>Produkt <\/b>(Textfeld)<\/li>\n<li><b>tblProduktbilder<\/b>: <b>ProduktbildID<\/b> (Prim&auml;rschl&uuml;sselfeld), <b>ProduktID <\/b>(Fremdschl&uuml;sselfeld zur Tabelle <b>tblProduktbilder<\/b>), <b>Produktbild <\/b>(Datentyp <b>varbinary(max)<\/b>)<\/li>\n<\/ul>\n<p>Um die Tabellen schnell zu erstellen, k&ouml;nnen wir das folgende Skript nutzen:<\/p>\n<pre>CREATE TABLE tblProdukte (    ProduktID INT IDENTITY(1,1) PRIMARY KEY,    Produkt NVARCHAR(255) NOT NULL);CREATE TABLE tblProduktbilder (    ProduktbildID INT IDENTITY(1,1) \r\n         PRIMARY KEY,    ProduktID INT NOT NULL,    Produktbild VARBINARY(MAX) NOT NULL,    CONSTRAINT FK_Produktbilder_Produkte         FOREIGN KEY (ProduktID)         REFERENCES tblProdukte (ProduktID)             ON DELETE CASCADE);<\/pre>\n<p>Danach k&ouml;nnen wir uns an die Erstellung des Codes zum &Uuml;bertragen der Daten samt Bilddaten begeben.<\/p>\n<h2>Notwendiger Parameter zum &Uuml;bertragen der Tabelle inklusive Anlagefeld<\/h2>\n<p>Im Beitrag <b>Anlage-Feld zum SQL Server migrieren <\/b>(<b>www.access-im-unternehmen.de\/1542<\/b>) haben wir bereits eine Funktion programmiert, die wir komplett &uuml;ber Parameter steuern k&ouml;nnen.<\/p>\n<p>Im vorliegenden Beitrag ben&ouml;tigen wir eine &auml;hnliche Prozedur, die allerdings noch einige weitere Parameter ben&ouml;tigt. Immerhin sollen die Daten aus urspr&uuml;nglich einer Tabelle nun auf zwei Tabellen aufgeteilt werden.<\/p>\n<p>Zuvor legen wir fest, wie wir hier vorgehen wollen. M&ouml;chten wir eine &auml;hnliche Prozedur schreiben, wie wir sie im oben genannten Beitrag angelegt haben, die f&uuml;r eine bereits bestehende Migration inklusive Daten nur noch die Inhalte der Anlagefelder hinterherkopiert? Dies ist in den F&auml;llen interessant, wo man die &uuml;brige Migration bereits vollst&auml;ndig durchgef&uuml;hrt hat, beispielsweise mit einem Tool wie SQL Server Migration Assistant.<\/p>\n<p>In diesem Beitrag wollen wir jedoch eine L&ouml;sung kreieren, welche die Inhalte der Tabellen vollst&auml;ndig &uuml;bertr&auml;gt.<\/p>\n<p>Wir gehen also von den leeren Tabellen <b>tblProdukte <\/b>und <b>tblProduktbilder <\/b>auf dem SQL Server aus und wollen alle enthaltenen Informationen dorthin &uuml;bertragen.<\/p>\n<p>Wir werden also in den folgenden Schritten vorgehen:<\/p>\n<ul>\n<li>&Uuml;bertragen eines Datensatzes der Tabelle <b>tblProdukte <\/b>zur gleichnamigen SQL Server-Tabelle (mit Ausnahme des Anlagefeldes)<\/li>\n<li>Merken des neuen Prim&auml;rschl&uuml;sselwertes<\/li>\n<li>Durchlaufen der Anlagen und schrittweises &Uuml;bertragen der Anlagen in die Tabelle <b>tblProdukteBilder<\/b>, wobei wir den gemerkten Prim&auml;rschl&uuml;sselwert als Fremdschl&uuml;sselwert nutzen<\/li>\n<\/ul>\n<p>F&uuml;r die Parametrisierung ben&ouml;tigen wir also die folgenden Daten:<\/p>\n<ul>\n<li><b>strAccessTable<\/b>: Name der Haupttabelle<\/li>\n<li><b>strAccessField<\/b>: Name des Anlagefeldes der Haupttabelle<\/li>\n<li><b>strAccessPKField<\/b>: Name des Prim&auml;rschl&uuml;sselfeldes der Haupttabelle<\/li>\n<li><b>lngAccessPKID<\/b>: Wert des Prim&auml;rschl&uuml;sselfeldes des aktuellen Datensatzes<\/li>\n<li><b>strSQLTable<\/b>: Name der Haupttabelle im SQL Server<\/li>\n<li><b>strSQLPKField<\/b>: Name des Prim&auml;rschl&uuml;sselfeldes der Haupttabelle im SQL Server<\/li>\n<li><b>strSQLAttachmentTable<\/b>: Name der Anlagentabelle im SQL Server<\/li>\n<li><b>strSQLAttachmentPKField<\/b>: Name des Prim&auml;rschl&uuml;sselfeldes der Anlagentabelle im SQL Server<\/li>\n<li><b>strSQLVarBinaryMaxField<\/b>: Name des <b>varbinary(max)<\/b>-Feldes in der Anlagentabelle der SQL Server-Datenbank<\/li>\n<li><b>strSQLAttachmentFKField<\/b>: Name des Fremdschl&uuml;sselfeldes der Anlagentabelle im SQL Server<\/li>\n<li><b>cnn<\/b>: Verbindung zum SQL Server<\/li>\n<li><b>db<\/b>: Verweis auf das aktuelle <b>Database<\/b>-Objekt<\/li>\n<li><b>strErrorMessage<\/b>: R&uuml;ckgabeparameter f&uuml;r Fehlermeldungen<\/li>\n<\/ul>\n<h2>Aufruf der Funktionen<\/h2>\n<p>Den Start machen wir mit der Prozedur <b>TabelleMitMehrfachanlagenZumSQLServer<\/b> (siehe Listing 1). Diese erstellt einen Verweis auf das aktuelle <b>Database<\/b>-Objekt sowie eine Connection auf die entsprechende SQL Server-Datenbank.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabelleMitMehrfachanlagenZumSQLServer()\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>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strErrorMessage<span style=\"color:blue;\"> As String<\/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>rstResult<span style=\"color:blue;\"> As <\/span>ADODB.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\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 tblProdukte\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         strSQL = \"INSERT INTO tblProdukte(Produkt) OUTPUT INSERTED.ProduktID  VALUES(''\" & rst!Produkt & \"'');\"\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!ProduktID\r\n             bolKopiert = CopyAttachmentToVarBinaryMax_Multi(\"tblProdukte\", \"Produktbilder\", \"ProduktID\", _\r\n                 rst!ProduktID, lngID, \"tblProduktbilder\", \"Produktbild\", \"ProduktID\", cnn, db, strErrorMessage)\r\n             <span style=\"color:blue;\">If <\/span>bolKopiert = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">MsgBox<\/span> \"Datensatz \" & rst!ProduktID & \" erfolgreich kopiert.\"\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 <span style=\"color:blue;\">MsgBox<\/span> \"Datensatz \" & rst!ProduktID & \" 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;\">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     rst.Close\r\n     <span style=\"color:blue;\">Set<\/span> rst = Nothing\r\n     <span style=\"color:blue;\">Set<\/span> db = Nothing\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: Aufruf der Funktionen zum Kopieren von Tabellen mit Anlagefeldern mit mehreren Dateien<\/span><\/b><\/p>\n<p>Die daf&uuml;r notwendige Verbindungszeichenfolge haben wir in diesem Fall wie folgt in einer Konstanten hinterlegt:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Const cStrConnection<span style=\"color:blue;\"> As String<\/span> = \"Provider=MSOLEDBSQL;Data Source=amvdesktop2023;Initial Catalog=Anlagen;Integrated Security=SSPI;\"<\/pre>\n<p>Die Verbindung &ouml;ffnet die Prozedur dann mit der <b>Open<\/b>-Methode. Au&szlig;erdem f&uuml;llen wir ein Recordset mit den Datens&auml;tze der Tabelle <b>tblProdukte <\/b>und durchlaufen dieses in einer <b>Do While<\/b>-Schleife &uuml;ber alle Datens&auml;tze.<\/p>\n<p>Darin kopieren wir zun&auml;chst die Daten dieser Tabelle mit Ausnahme des Anlagefeldes. Dazu erstellen wir eine entsprechende <b>INSERT INTO<\/b>-Anweisung.<\/p>\n<p>Diese wollen wir mithilfe eines <b>Command<\/b>-Objekts ausf&uuml;hren, dem wir die Verbindung aus <b>cnn <\/b>zuweisen und f&uuml;r das wir die <b>INSERT INTO<\/b>-Anweisung als <b>CommandText <\/b>hinterlegen.<\/p>\n<p>Die <b>INSERT INTO<\/b>-Anweisung hat die Besonderheit, dass wir in ihr mit <b>OUTPUT INSERTED.ProduktID <\/b>direkt den Prim&auml;rschl&uuml;sselwert des neu erstellten Datensatzes ermitteln. Um diesen sp&auml;ter auszulesen, speichern wir das Ergebnis der <b>Execute<\/b>-Methode in einem Recordset namens <b>rstResults<\/b>.<\/p>\n<p>Mit dieser <b>ProduktID <\/b>ausgestattet rufen wir die Funktion <b>CopyAttachmentToVarBinaryMax_Multi <\/b>auf. Dieser &uuml;bergeben wir die oben genannten Parameter f&uuml;r das Kopieren der Datens&auml;tze der Tabelle <b>tblProdukte <\/b>in die beiden Tabellen <b>tblProdukte <\/b>und <b>tblProduktbilder <\/b>auf dem SQL Server.<\/p>\n<p>War die Ausf&uuml;hrung dieser Funktion und der von dieser aufgerufenen Unterfunktionen erfolgreich, erscheint eine entsprechende Meldung.<\/p>\n<p>Auf diese Weise werden alle Datens&auml;tze durchlaufen und zum SQL Server &uuml;bertragen.<\/p>\n<h2>Funktion zum Durchf&uuml;hren des Kopiervorgangs<\/h2>\n<p>Die Funktion <b>CopyAttachmentToVarBinaryMax_Multi <\/b>ist die Steuerzentrale des Vorgangs (siehe Listing 2). Sie erstellt ein Recordset auf Basis der Tabelle mit den zu kopierenden Daten des aktuellen Datensatzes der aufrufenden Tabelle inklusive Anlagen. Au&szlig;erdem erstellt sie ein weiteres Recordset namens <b>rstAttachments<\/b>, das die Datens&auml;tze in der internen Tabelle mit den Anlagen des Feldes <b>Produktbilder <\/b>enth&auml;lt.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>CopyAttachmentToVarBinaryMax_Multi(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>, lngSQLPKID<span style=\"color:blue;\"> As Long<\/span>, strSQLAttachmentTable<span style=\"color:blue;\"> As String<\/span>, _\r\n         strSQLVarBinaryMaxField<span style=\"color:blue;\"> As String<\/span>, strSQLAttachmentFKField<span style=\"color:blue;\"> As String<\/span>, cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection, _\r\n         db<span style=\"color:blue;\"> As <\/span>DAO.Database, <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     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstAttachments<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>lngCopycount<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT \" & strAccessField & \" FROM \" & strAccessTable & \" WHERE \" & strAccessPKField _\r\n         & \" = \" & lngAccessPKID, dbOpenDynaset)\r\n     <span style=\"color:blue;\">Set<\/span> rstAttachments = rst.Fields(strAccessField).Value\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstAttachments.EOF\r\n         <span style=\"color:blue;\">If <\/span>SaveAttachmentToFile_Multi(rstAttachments, strFilepath) = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\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_Multi(cnn, strSQLAttachmentTable, strSQLVarBinaryMaxField, _\r\n                         strSQLAttachmentFKField, lngSQLPKID, bytData, strErrorMessage) = <span style=\"color:blue;\">True<\/span> Then\r\n                     lngCopycount = lngCopycount + 1\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         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         rstAttachments.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     <span style=\"color:blue;\">If <\/span>lngCopycount = rstAttachments.RecordCount<span style=\"color:blue;\"> Then<\/span>\r\n         CopyAttachmentToVarBinaryMax_Multi = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         strErrorMessage = \"Nur \" & lngCopycount & \" von \" & rstAttachments.RecordCount & \" Datens&auml;tze kopiert.\"\r\n         CopyAttachmentToVarBinaryMax_Multi = <span style=\"color:blue;\">False<\/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 der Attachments einer Tabelle in eine SQL Server-Tabelle<\/span><\/b><\/p>\n<p>Sie durchl&auml;uft nun alle Datens&auml;tze des Recordsets <b>rstAttachments<\/b>, also alle Anlagen des aktuellen Datensatzes, in einer <b>Do While<\/b>-Schleife. Darin ruft sie zun&auml;chst die Funktion <b>SaveAttachmentToFile_Multi <\/b>auf, die daf&uuml;r sorgt, dass das Attachment des aktuellen Datensatzes des Recordsets <b>rstAttachments <\/b>im Dateisystem gespeichert wird und den Namen der angelegten Datei zur&uuml;ckliefert. <\/p>\n<p>War dieser Vorgang erfolgreich, ruft die Funktion <b>CopyAttachmentToVarBinaryMax_Multi <\/b>die n&auml;chste Funktion <b>LoadFileToByteArray <\/b>auf. Diese l&auml;dt die zuvor im Dateisystem gespeicherte Datei in ein Byte-Array, das als Parameter zur&uuml;ckgegeben wird. War auch dies erfolgreich, folgt die n&auml;chste Funktion namens <b>AddByteArrayToVarBinaryMax_Multi<\/b>, die schlie&szlig;lich den Inhalt des Byte-Arrays in das <b>varbinary(max)<\/b>-Feld der Zieltabelle <b>tblProduktbilder <\/b>speichert. F&uuml;r jeden erfolgreichen Vorgang wird der Z&auml;hler <b>lngCopycount <\/b>um 1 erh&ouml;ht, damit wir anschlie&szlig;end pr&uuml;fen k&ouml;nnen, ob alle Anlagen erfolgreich gespeichert wurden.<\/p>\n<p>Entspricht nach dem Durchlaufen aller Attachments der Wert aus <b>lngCopycount <\/b>der Anzahl der Datens&auml;tze aus <b>rstAttachments<\/b>, war der Vorgang insgesamt erfolgreich und die Funktion gibt den Wert <b>True <\/b>zur&uuml;ck. Anderenfalls erscheint eine entsprechende Fehlermeldung.<\/p>\n<h2>Funktion zum Speichern der Anlagen in eine Datei<\/h2>\n<p>Die oben erw&auml;hnte Funktion <b>SaveAttachmentToFile_Multi <\/b>ermittelt den Dateinamen aus dem Feld <b>Filename <\/b>des &uuml;bergebenen Recordsets mit den Anlagen und liest daraus die Dateiendung aus (siehe Listing 3). Mit dem aktuellen Datenbankpfad, dem Dateinamen <b>temp <\/b>und der Dateiendung wird der Dateipfad zusammengesetzt.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>SaveAttachmentToFile_Multi(rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset, strFilepath<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\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     strFilename = rst(\"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     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(Dir(strFilepath)) = 0\r\n         Kill strFilepath\r\n         DoEvents\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     \r\n     rst.Fields(\"FileData\").SaveToFile strFilepath\r\n     SaveAttachmentToFile_Multi = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Funktion zum Speichern der Attachments in einer Datei<\/span><\/b><\/p>\n<p>Die Prozedur durchl&auml;uft anschlie&szlig;end solange eine <b>Do While<\/b>-Schleife, in der sie die eventuell bereits unter diesem Namen vorhandene Datei l&ouml;scht, bis diese nicht mehr vorhanden ist. Anschlie&szlig;end erstellt sie diese mit der <b>SaveToFile<\/b>-Methode aus dem aktuellen Anlagefeld neu.<\/p>\n<h2>Funktion zum F&uuml;llen eines Byte-Arrays aus der Datei<\/h2>\n<p>Die Funktion <b>LoadFileToByteArray <\/b>aus Listing 4 dient dazu, ein <b>ADODB.Stream<\/b>-Objekt zu erstellen und dieses mit dem Inhalt aus der zuvor gespeicherten Datei zu f&uuml;llen.<\/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 Einlesen des Attachments aus einer Datei in ein Byte-Array<\/span><\/b><\/p>\n<p>Dazu nutzt sie die <b>LoadFromFile<\/b>-Methode des <b>Stream<\/b>-Objekts und gibt das <b>Byte<\/b>-Array &uuml;ber den R&uuml;ckgabeparameter <b>bytData <\/b>zur&uuml;ck.<\/p>\n<h2>Funktion zum Speichern des Byte-Arrays in einem varbinary(max)-Feld<\/h2>\n<p>Die letzte Funktion namens <b>AddByteArrayToVarBinaryMax_Multi <\/b>aus Listing 5 dient dazu, den Inhalt des Byte-Arrays im Anlagefeld eines neuen Datensatzes der Tabelle <b>tblProduktbilder <\/b>zu speichern. Dazu erstellt sie ein neues <b>Command<\/b>-Objekt namens <b>cmd<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddByteArrayToVarBinaryMax_Multi(cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection, strAttachmentTable<span style=\"color:blue;\"> As String<\/span>, _\r\n         strAttachmentField<span style=\"color:blue;\"> As String<\/span>, strAttachmentFKField<span style=\"color:blue;\"> As String<\/span>, lngSQLPKID<span style=\"color:blue;\"> As Long<\/span>, bytData()<span style=\"color:blue;\"> As Byte<\/span>, _\r\n         <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;\">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     <span style=\"color:blue;\">With<\/span> cmd\r\n         .ActiveConnection = cnn\r\n         .CommandType = adCmdText\r\n         .CommandText = \"INSERT INTO \" & strAttachmentTable & \"(\" & strAttachmentFKField & \", \" & strAttachmentField _\r\n             & \") VALUES(\" & 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) - <span style=\"color:blue;\">LBound<\/span>(bytData) + 1, _\r\n                 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_Multi = <span style=\"color:blue;\">True<\/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 Schreiben des Byte-Arrays in einen neuen Datensatz der Tabelle tblProduktbilder<\/span><\/b><\/p>\n<p>Diesem wird die Connection <b>cnn<\/b> und eine <b>INSERT INTO<\/b>-Anweisung hinzugef&uuml;gt, die mit einem Fragezeichen Platz f&uuml;r einen sp&auml;ter einzuf&uuml;genden Parameter bereith&auml;lt &#8211; hier mit den Tabellen- und Feldnamen f&uuml;r unseren Anwendungsfall sowie dem Beispielwert <b>1 <\/b>f&uuml;r das Fremdschl&uuml;sselfeld <b>ProduktID<\/b> versehen:<\/p>\n<pre>INSERT INTO tblProduktbilder(ProduktID, Produktbild) VALUES(1, ?)<\/pre>\n<p>Wenn <b>bytData<\/b>, also das Byte-Array nicht leer ist, f&uuml;llt die Funktion dessen Inhalt in ein <b>Parameter<\/b>-Objekt namens <b>prm <\/b>und h&auml;ngt dieses an die <b>Parameters<\/b>-Auflistung des <b>Command<\/b>-Objekts an.<\/p>\n<p>Damit ausgestattet ist das <b>Command<\/b>-Objekt bereit zum Ausf&uuml;hren mit der <b>Execute<\/b>-Methode. Diese liefert die Anzahl der betroffenen Datens&auml;tze mit der Variablen <b>lngRecordsAffected <\/b>zur&uuml;ck.<\/p>\n<h2>Ergebnis des Kopiervorgangs<\/h2>\n<p>Zum Testen haben wir nun ein paar Beispieldaten zu unserer Tabelle <b>tblProdukte <\/b>in der Access-Datenbank hinterlegt (siehe Bild 5).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1546_006.png\" alt=\"Die zu kopierenden Daten in der Access-Anwendung\" width=\"599,559\" height=\"383,7177\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Die zu kopierenden Daten in der Access-Anwendung<\/span><\/b><\/p>\n<p>Diese wollen wir nun zum SQL Server kopieren, sodass die Daten der Tabelle <b>tblProdukte <\/b>bis auf die Daten im Anlagefeld <b>Produktbilder<\/b> in der Tabelle <b>tblProdukte <\/b>auf dem SQL Server landen. Die Daten der Anlagefelder hingegen sollen in jeweils einen Datensatz der Tabelle <b>tblProduktebilder <\/b>im SQL Server geschrieben werden. Dabei soll das Fremdschl&uuml;sselfeld <b>ProduktID <\/b>dieser Tabelle mit dem Datensatz der Tabelle <b>tblProdukte <\/b>verkn&uuml;pft werden, aus der die Bilder urspr&uuml;nglich stammen.<\/p>\n<p>Genau das erledigt unsere Prozedur <b>TabelleMitMehrfachanlagenZumSQLServer<\/b>, die nacheinander die hier vorstellten Funktionen aufruft. Das Ergebnis sieht schlie&szlig;lich wie in Bild 6 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1546_005.png\" alt=\"Frisch zum SQL Server kopierte Daten samt Anlagen in einer eigenen Tabelle\" width=\"700\" height=\"291,7443\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Frisch zum SQL Server kopierte Daten samt Anlagen in einer eigenen Tabelle<\/span><\/b><\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Dieser Beitrag zeigt, wie wir Daten aus Tabellen, die mehr als eine Anlage pro Anlagefeld enthalten, in entsprechende Tabellen im SQL Server kopieren k&ouml;nnen. Das Formular frmProduktbilder zeigt, nachdem Sie die Tabellenverkn&uuml;pfung <b>tblProdukte_SQL <\/b>und <b>tblProduktbilder <\/b>auf die entsprechenden Tabellen im SQL Server eingestellt haben, dass das &Uuml;bertragen der Anlagen wie gew&uuml;nscht funktioniert hat. Eine weitere Aufgabe w&auml;re nun noch, eine Darstellung zu realisieren, die zu einem Produkt alle Bilder in einem Unterformular oder einem anderen geeigneten Steuerelement anzeigt oder diese in einem Bild-Steuerelement zum Durchbl&auml;ttern anbietet.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>MultiAttachmentZumSQLServerMigrieren.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/D0D3F968-1D11-470A-ACA3-81C94EF9F1AC\/aiu_1546.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Beitrag &#8222;Anlage-Feld zum SQL Server migrieren&#8220; (www.access-im-unternehmen.de\/1542) haben wir gezeigt, wie Inhalte von Anlagefeldern einer Access-Datenbank in ein varbinary(max)-Feld einer SQL Server-Datenbank &uuml;bertragen werden k&ouml;nnen. Dort sind wir davon ausgegangen, dass jedes Anlagefeld immer nur eine Datei enth&auml;lt, was in vielen F&auml;llen ausreichend ist. Was aber, wenn der Entwickler das Anlagefeld f&uuml;r mehrere Dateien vorgesehen hat &#8211; beispielsweise, um ein oder mehrere Produktbilder zu einem Produkt zu speichern? In diesem Fall m&uuml;ssen wir umdenken, denn wir k&ouml;nnen optimalerweise immer nur eine Datei in einem varbinary(max)-Feld speichern. Zum Speichern mehrerer Dateien m&uuml;ssen wir uns also einen Workaround &uuml;berlegen. Wie dieser aussieht, schauen wir uns im vorliegenden Beitrag an.<\/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-55001546","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>Anlagefelder mit mehreren Dateien zum SQL Server - 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\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Anlagefelder mit mehreren Dateien zum SQL Server\" \/>\n<meta property=\"og:description\" content=\"Im Beitrag &quot;Anlage-Feld zum SQL Server migrieren&quot; (www.access-im-unternehmen.de\/1542) haben wir gezeigt, wie Inhalte von Anlagefeldern einer Access-Datenbank in ein varbinary(max)-Feld einer SQL Server-Datenbank &uuml;bertragen werden k&ouml;nnen. Dort sind wir davon ausgegangen, dass jedes Anlagefeld immer nur eine Datei enth&auml;lt, was in vielen F&auml;llen ausreichend ist. Was aber, wenn der Entwickler das Anlagefeld f&uuml;r mehrere Dateien vorgesehen hat - beispielsweise, um ein oder mehrere Produktbilder zu einem Produkt zu speichern? In diesem Fall m&uuml;ssen wir umdenken, denn wir k&ouml;nnen optimalerweise immer nur eine Datei in einem varbinary(max)-Feld speichern. Zum Speichern mehrerer Dateien m&uuml;ssen wir uns also einen Workaround &uuml;berlegen. Wie dieser aussieht, schauen wir uns im vorliegenden Beitrag an.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2025-05-07T12:08:50+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg02.met.vgwort.de\/na\/6ae36d3b4a8048ce8d2c352685ad10ab\" \/>\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=\"13\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Anlagefelder mit mehreren Dateien zum SQL Server\",\"datePublished\":\"2025-05-07T12:08:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/\"},\"wordCount\":2027,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/6ae36d3b4a8048ce8d2c352685ad10ab\",\"articleSection\":[\"2025\",\"3\\\/2025\",\"SQL Server und Co.\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/\",\"name\":\"Anlagefelder mit mehreren Dateien zum SQL Server - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/6ae36d3b4a8048ce8d2c352685ad10ab\",\"datePublished\":\"2025-05-07T12:08:50+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/6ae36d3b4a8048ce8d2c352685ad10ab\",\"contentUrl\":\"http:\\\/\\\/vg02.met.vgwort.de\\\/na\\\/6ae36d3b4a8048ce8d2c352685ad10ab\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Anlagefelder mit mehreren Dateien zum SQL Server\"}]},{\"@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":"Anlagefelder mit mehreren Dateien zum SQL Server - 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\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/","og_locale":"de_DE","og_type":"article","og_title":"Anlagefelder mit mehreren Dateien zum SQL Server","og_description":"Im Beitrag \"Anlage-Feld zum SQL Server migrieren\" (www.access-im-unternehmen.de\/1542) haben wir gezeigt, wie Inhalte von Anlagefeldern einer Access-Datenbank in ein varbinary(max)-Feld einer SQL Server-Datenbank &uuml;bertragen werden k&ouml;nnen. Dort sind wir davon ausgegangen, dass jedes Anlagefeld immer nur eine Datei enth&auml;lt, was in vielen F&auml;llen ausreichend ist. Was aber, wenn der Entwickler das Anlagefeld f&uuml;r mehrere Dateien vorgesehen hat - beispielsweise, um ein oder mehrere Produktbilder zu einem Produkt zu speichern? In diesem Fall m&uuml;ssen wir umdenken, denn wir k&ouml;nnen optimalerweise immer nur eine Datei in einem varbinary(max)-Feld speichern. Zum Speichern mehrerer Dateien m&uuml;ssen wir uns also einen Workaround &uuml;berlegen. Wie dieser aussieht, schauen wir uns im vorliegenden Beitrag an.","og_url":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/","og_site_name":"Access im Unternehmen","article_published_time":"2025-05-07T12:08:50+00:00","og_image":[{"url":"http:\/\/vg02.met.vgwort.de\/na\/6ae36d3b4a8048ce8d2c352685ad10ab","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"13\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Anlagefelder mit mehreren Dateien zum SQL Server","datePublished":"2025-05-07T12:08:50+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/"},"wordCount":2027,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/#primaryimage"},"thumbnailUrl":"http:\/\/vg02.met.vgwort.de\/na\/6ae36d3b4a8048ce8d2c352685ad10ab","articleSection":["2025","3\/2025","SQL Server und Co."],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/","url":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/","name":"Anlagefelder mit mehreren Dateien zum SQL Server - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/#primaryimage"},"thumbnailUrl":"http:\/\/vg02.met.vgwort.de\/na\/6ae36d3b4a8048ce8d2c352685ad10ab","datePublished":"2025-05-07T12:08:50+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/#primaryimage","url":"http:\/\/vg02.met.vgwort.de\/na\/6ae36d3b4a8048ce8d2c352685ad10ab","contentUrl":"http:\/\/vg02.met.vgwort.de\/na\/6ae36d3b4a8048ce8d2c352685ad10ab"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Anlagefelder_mit_mehreren_Dateien_zum_SQL_Server\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Anlagefelder mit mehreren Dateien zum SQL Server"}]},{"@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\/55001546","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=55001546"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001546\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001546"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001546"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001546"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}