{"id":55000520,"date":"2026-08-01T00:00:00","date_gmt":"2026-10-18T13:18:05","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=520"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"SQL_Server_PDFs_in_varbinarymaxFeld_speichern","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/","title":{"rendered":"SQL Server: PDFs in varbinary(max)-Feld speichern"},"content":{"rendered":"<p><b>Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w&auml;hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel&ouml;scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth&auml;lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf&uuml;r nimmt der Datentyp <b>varbinary(max)<\/b> Bin&auml;rdaten bis zu einer Gr&ouml;&szlig;e von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit <b>ADODB<\/b> in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.<\/b><\/p>\n<h2>Szenario und Beispieldatenbank<\/h2>\n<p>Zu den Datens&auml;tzen einer kleinen Dokumentenverwaltung soll jeweils ein PDF-Dokument geh&ouml;ren, zum Beispiel eine Rechnung, ein Angebot oder ein Lieferschein.<\/p>\n<p>Die Beispieldatenbank <b>PDFInVarCharMax<\/b> enth&auml;lt dazu eine Tabelle mit drei Feldern:<\/p>\n<ul>\n<li><b>PDFID:<\/b> der Prim&auml;rschl&uuml;ssel vom Datentyp <b>int<\/b> mit der Eigenschaft <b>IDENTITY<\/b>, die dem AutoWert in Access entspricht<\/li>\n<li><b>Dateiname:<\/b> der Name der Datei vom Datentyp <b>nvarchar(255)<\/b><\/li>\n<li><b>Dateiinhalt:<\/b> der Inhalt der Datei vom Datentyp <b>varbinary(max)<\/b><\/li>\n<\/ul>\n<p>Die Tabelle legen wir mit der folgenden Anweisung an, wobei <b>dbo<\/b> das Standardschema des SQL Servers ist. Das Skript <b>PDFInVarCharMax.sql<\/b> aus dem Download legt zus&auml;tzlich die Datenbank an.<\/p>\n<p>Wir f&uuml;hren es im SQL Server Management Studio (SSMS) aus. Das Skript pr&uuml;ft vor jeder Anweisung, ob das Objekt schon existiert. Deshalb k&ouml;nnen wir es mehrmals ausf&uuml;hren.<\/p>\n<pre>CREATE TABLE dbo.tblPDFs (\r\n    PDFID int IDENTITY(1, 1) NOT NULL\r\n        CONSTRAINT PK_tblPDFs PRIMARY KEY,\r\n    Dateiname nvarchar(255) NOT NULL,\r\n    Dateiinhalt varbinary(max) NULL\r\n);<\/pre>\n<p>Das Feld <b>Dateiinhalt<\/b> erlaubt den Wert <b>NULL<\/b>. Damit k&ouml;nnen wir auch Datens&auml;tze anlegen, die kein PDF-Dokument enthalten. Diesen Fall behandeln wir im Formular zur Anzeige der PDF-Dokumente gesondert.<\/p>\n<h2>Der Datentyp varbinary(max)<\/h2>\n<p>Der Datentyp <b>varbinary(n)<\/b> speichert h&ouml;chstens 8.000 Byte. Geben wir statt <b>n<\/b> den Wert <b>max<\/b> an, nimmt das Feld bis zu 2.147.483.647 Byte auf, was knapp 2 Gigabyte entspricht.<\/p>\n<p>Der SQL Server speichert die Datei als Folge von Bytes, ohne ihre Struktur zu kennen. Dass es sich um ein PDF-Dokument handelt, erkennen wir in der Tabelle nur am Dateinamen.<\/p>\n<p>Die L&auml;nge eines Werts in Byte liefert die Funktion <b>DATALENGTH()<\/b>. Enth&auml;lt das Feld den Wert <b>NULL<\/b>, liefert sie ebenfalls <b>NULL<\/b>. Die folgende Abfrage zeigt die Gr&ouml;&szlig;e der gespeicherten Dateien:<\/p>\n<pre>SELECT PDFID, Dateiname,\r\n       DATALENGTH(Dateiinhalt) AS Groesse\r\nFROM dbo.tblPDFs;<\/pre>\n<p>Ein Feld mit der L&auml;nge 0 Byte, geschrieben als <b>0x<\/b>, unterscheidet sich vom Wert <b>NULL<\/b>, der f&uuml;r einen fehlenden Wert steht.<\/p>\n<p>F&uuml;r die Anzeige im Formular behandeln wir beide F&auml;lle gleich. Enth&auml;lt das Feld keine Bytes, haben wir kein PDF-Dokument gespeichert.<\/p>\n<h2>Die Verbindung zum SQL Server<\/h2>\n<p>Die Beispiele verwenden <b>ADODB<\/b>. Daf&uuml;r braucht das Projekt einen Verweis auf die <b>Microsoft ActiveX Data Objects 6.1 Library<\/b>. Die Funktionen und Prozeduren dieses Beitrags stehen im Modul <b>mdlPDFInVarBinaryMax<\/b>.<\/p>\n<p>Am Anfang des Moduls legen wir den Server und die Datenbank als Konstanten fest. Hier tragen wir den Namen des eigenen Servers ein. In den Beispielen hei&szlig;t er <b>amvDesktop2023<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>Const cstrServer<span style=\"color:blue;\"> As String<\/span> = \"amvDesktop2023\"\r\n<span style=\"color:blue;\">Private <\/span>Const cstrDatenbank _\r\n   <span style=\"color:blue;\"> As String<\/span> = \"PDFInVarCharMax\"<\/pre>\n<p>Die Funktion <b>Verbindung<\/b> setzt daraus die Verbindungszeichenfolge f&uuml;r den ODBC-Treiber zusammen (siehe Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>Verbindung(<span style=\"color:blue;\">Optional<\/span> ByVal strDatenbank<span style=\"color:blue;\"> As String<\/span> = cstrDatenbank)<span style=\"color:blue;\"> As String<\/span>\r\n    Verbindung = \"Driver={ODBC Driver 18 for SQL Server};Server=\" & cstrServer & _\r\n        \";Database=\" & strDatenbank & _\r\n        \";Trusted_Connection=Yes;Encrypt=yes;TrustServerCertificate=yes;\"\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Verbindung liefert die Verbindungszeichenfolge<\/span><\/b><\/p>\n<p>Mit <b>Trusted_Connection=Yes<\/b> verwenden wir die Windows-Anmeldung.<\/p>\n<p>Der ODBC-Treiber 18 verschl&uuml;sselt die Verbindung standardm&auml;&szlig;ig, wobei <b>TrustServerCertificate=yes<\/b> die Pr&uuml;fung des Serverzertifikats unterdr&uuml;ckt. Das gen&uuml;gt f&uuml;r die Beispiele. Auf einem Produktivserver installieren wir ein vertrauensw&uuml;rdiges Zertifikat. &Uuml;bergeben wir der Funktion keinen Datenbanknamen, verwendet sie die Konstante <b>cstrDatenbank<\/b>.<\/p>\n<h2>Die Datenbank und die Tabelle per VBA-Prozedur anlegen<\/h2>\n<p>Wer das Skript nicht im SSMS ausf&uuml;hren m&ouml;chte, legt die Datenbank und die Tabelle per VBA-Prozedur an. Die Prozedur <b>DatenbankAnlegen<\/b> verbindet sich dazu mit der Systemdatenbank <b>master<\/b> und legt die Datenbank an (siehe Listing 2).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>DatenbankAnlegen(<span style=\"color:blue;\">Optional<\/span> ByVal strDatenbank<span style=\"color:blue;\"> As String<\/span> = cstrDatenbank)\r\n    <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n    <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n    cnn.Open Verbindung(\"master\")\r\n    cnn.Execute \"IF DB_ID(N'\" & strDatenbank & \"') IS NULL \" & _\r\n        \"CREATE DATABASE [\" & strDatenbank & \"]\"\r\n    cnn.Close\r\n    cnn.Open Verbindung(strDatenbank)\r\n    cnn.Execute \"IF OBJECT_ID(N'dbo.tblPDFs', N'U') IS NULL \" & _\r\n        \"CREATE TABLE dbo.tblPDFs (\" & _\r\n        \"PDFID int IDENTITY(1, 1) NOT NULL CONSTRAINT PK_tblPDFs PRIMARY KEY, \" & _\r\n        \"Dateiname nvarchar(255) NOT NULL, \" & _\r\n        \"Dateiinhalt varbinary(max) NULL)\"\r\n    cnn.Close\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: DatenbankAnlegen legt die Datenbank und die Tabelle an<\/span><\/b><\/p>\n<p>Anschlie&szlig;end &ouml;ffnet sie eine Verbindung zu dieser Datenbank und legt die Tabelle an. Beide Anweisungen f&uuml;hrt sie nur aus, falls das Objekt noch nicht existiert. F&uuml;r die Datenbank braucht das Konto, mit dem wir uns anmelden, das Recht <b>CREATE DATABASE<\/b>. Die Prozedur setzt den Datenbanknamen unver&auml;ndert in die Anweisung ein. Daher &uuml;bergeben wir nur eigene, feste Namen.<\/p>\n<p>Im Direktbereich rufen wir die Prozedur auf. Fehlen die Datenbank und die Tabelle, legt der Aufruf beide an. Existieren sie bereits, &auml;ndert er nichts:<\/p>\n<pre>DatenbankAnlegen<\/pre>\n<h2>Ein PDF-Dokument speichern<\/h2>\n<p>Die Funktion <b>PDFInSQLSpeichern<\/b> liest eine Datei und schreibt sie in die Tabelle (siehe Listing 3). Zuerst pr&uuml;ft sie mit der Methode <b>FileExists<\/b> des Objekts <b>FileSystemObject<\/b>, ob die Datei existiert. Falls nicht, l&ouml;st sie einen benutzerdefinierten Fehler aus (<b>vbObjectError + 1000<\/b>).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>PDFInSQLSpeichern(ByVal strDateipfad<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> ByVal strConnection<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Long<\/span>\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>cmd<span style=\"color:blue;\"> As <\/span>ADODB.Command\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>stm<span style=\"color:blue;\"> As <\/span>ADODB.Stream\r\n    <span style=\"color:blue;\">Dim <\/span>fso<span style=\"color:blue;\"> As Object<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>varData<span style=\"color:blue;\"> As Variant<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strDateiname<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> fso = CreateObject(\"Scripting.FileSystemObject\")\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> fso.FileExists(strDateipfad)<span style=\"color:blue;\"> Then<\/span>\r\n        Err.Raise vbObjectError + 1000, \"PDFInSQLSpeichern\", \"Die Datei \" & strDateipfad & \" existiert nicht.\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strConnection) = 0<span style=\"color:blue;\"> Then<\/span> strConnection = Verbindung()\r\n    <span style=\"color:blue;\">Set<\/span> stm = <span style=\"color:blue;\">New<\/span> ADODB.Stream\r\n    <span style=\"color:blue;\">With<\/span> stm\r\n        .Type = adTypeBinary\r\n        .Open\r\n        .LoadFromFile strDateipfad\r\n        varData = .Read\r\n        .Close\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">If <\/span>IsNull(varData)<span style=\"color:blue;\"> Then<\/span>\r\n        Err.Raise vbObjectError + 1001, \"PDFInSQLSpeichern\", \"Die Datei \" & strDateipfad & \" ist leer.\"\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    strDateiname = fso.GetFileName(strDateipfad)\r\n    <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n    cnn.Open strConnection\r\n    <span style=\"color:blue;\">Set<\/span> cmd = <span style=\"color:blue;\">New<\/span> ADODB.Command\r\n    <span style=\"color:blue;\">With<\/span> cmd\r\n        .ActiveConnection = cnn\r\n        .CommandType = adCmdText\r\n        .CommandText = \"SET NOCOUNT ON; \" _\r\n            & \"INSERT INTO dbo.tblPDFs (Dateiname, Dateiinhalt) VALUES (?, ?); \" _\r\n            & \"SELECT CAST(SCOPE_IDENTITY() AS int);\"\r\n        .Parameters.Append .CreateParameter(\"pDateiname\", adVarWChar, adParamInput, 255, strDateiname)\r\n        .Parameters.Append .CreateParameter(\"pDateiinhalt\", adLongVarBinary, adParamInput, <span style=\"color:blue;\">UBound<\/span>(varData) + 1, varData)\r\n        <span style=\"color:blue;\">Set<\/span> rst = .Execute\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    PDFInSQLSpeichern = rst.Fields(0).Value\r\n    rst.Close\r\n    cnn.Close\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: PDFInSQLSpeichern schreibt eine Datei in die Tabelle<\/span><\/b><\/p>\n<p>Danach &ouml;ffnet sie einen <b>ADODB.Stream<\/b> vom Typ <b>adTypeBinary<\/b> und l&auml;dt die Datei mit <b>LoadFromFile<\/b>. Den gesamten Inhalt liest sie mit <b>Read<\/b> in eine Variant-Variable. Bei einer leeren Datei liefert <b>Read<\/b> den Wert <b>Null<\/b>. Dann l&ouml;st die Funktion den benutzerdefinierten Fehler <b>vbObjectError + 1001<\/b> aus.<\/p>\n<p>Den Dateinamen ermittelt die Funktion mit der Methode <b>GetFileName<\/b> aus dem Pfad. Die Anweisung <b>INSERT<\/b> f&uuml;hrt sie &uuml;ber ein Objekt vom Typ <b>ADODB.Command<\/b> mit zwei Parametern aus. Der Parameter f&uuml;r den Dateinamen hat den Typ <b>adVarWChar<\/b>, der Parameter f&uuml;r den Inhalt den Typ <b>adLongVarBinary<\/b> mit der L&auml;nge des Byte-Arrays. Den Inhalt &uuml;bergeben wir als Parameter, weil ein Hexadezimalliteral in der SQL-Anweisung bei gro&szlig;en Dateien unpraktisch w&auml;re.<\/p>\n<p>Die Anweisung beginnt mit <b>SET NOCOUNT ON<\/b>. Damit sendet der Server keine Meldung &uuml;ber die Zahl der ge&auml;nderten Zeilen, und das Recordset enth&auml;lt das Ergebnis des <b>SELECT<\/b>. Dieses <b>SELECT<\/b> gibt mit <b>SCOPE_IDENTITY()<\/b> die neue <b>PDFID<\/b> zur&uuml;ck. Die Funktion liefert sie als Ergebnis.<\/p>\n<p>Mit dem optionalen Parameter <b>strConnection<\/b> k&ouml;nnen wir eine andere Verbindungszeichenfolge &uuml;bergeben.<\/p>\n<p>&Uuml;bergeben wir keine, verwendet die Funktion die Zeichenfolge, die <b>Verbindung<\/b> liefert.<\/p>\n<p>Im Direktbereich speichern wir die Datei <b>test.pdf<\/b> aus dem Ordner der Datenbank:<\/p>\n<pre>PDFInSQLSpeichern(CurrentProject.Path & \"\\test.pdf\")\r\n 1<\/pre>\n<p>In einer neuen Tabelle erh&auml;lt das Dokument die <b>PDFID<\/b> 1. Die Abfrage mit <b>DATALENGTH()<\/b> liefert f&uuml;r diesen Datensatz den Wert <b>155.264<\/b>, die Gr&ouml;&szlig;e der Datei in Byte. F&uuml;r die Bilder speichern wir auf demselben Weg die Datei <b>vbe_517.pdf<\/b> als zweiten Datensatz. Den dritten Datensatz legen wir ohne PDF-Dokument an. Das Feld <b>Dateiinhalt<\/b> bleibt dabei leer:<\/p>\n<pre>INSERT INTO dbo.tblPDFs (Dateiname)\r\nVALUES (N'ohne_Inhalt.pdf');<\/pre>\n<h2>Ein PDF-Dokument auf die Festplatte schreiben<\/h2>\n<p>Die Funktion <b>PDFAusSQLSpeichern<\/b> schreibt den Inhalt zur&uuml;ck in eine Datei (siehe Listing 4). Sie liest das Feld <b>Dateiinhalt<\/b> des Datensatzes mit der &uuml;bergebenen <b>PDFID<\/b> mit einem Objekt vom Typ <b>ADODB.Recordset<\/b>. Da wir die Daten nur einmal lesen, gen&uuml;gen die Cursorart <b>adOpenForwardOnly<\/b> und die Sperrart <b>adLockReadOnly<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>PDFAusSQLSpeichern(ByVal lngPDFID<span style=\"color:blue;\"> As Long<\/span>, _\r\n        ByVal strZieldatei<span style=\"color:blue;\"> As String<\/span>, _\r\n        <span style=\"color:blue;\">Optional<\/span> ByVal strConnection<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n    <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>ADODB.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>stm<span style=\"color:blue;\"> As <\/span>ADODB.Stream\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strConnection) = 0<span style=\"color:blue;\"> Then<\/span> strConnection = Verbindung()\r\n    <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n    cnn.Open strConnection\r\n    <span style=\"color:blue;\">Set<\/span> rst = <span style=\"color:blue;\">New<\/span> ADODB.Recordset\r\n    rst.Open \"SELECT Dateiinhalt FROM dbo.tblPDFs WHERE PDFID = \" & lngPDFID, _\r\n        cnn, adOpenForwardOnly, 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(\"Dateiinhalt\").ActualSize &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n            <span style=\"color:blue;\">Set<\/span> stm = <span style=\"color:blue;\">New<\/span> ADODB.Stream\r\n            <span style=\"color:blue;\">With<\/span> stm\r\n                .Type = adTypeBinary\r\n                .Open\r\n                .Write rst.Fields(\"Dateiinhalt\").Value\r\n                .SaveToFile strZieldatei, adSaveCreateOverWrite\r\n                .Close\r\n            End <span style=\"color:blue;\">With<\/span>\r\n            PDFAusSQLSpeichern = <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\n    rst.Close\r\n    cnn.Close\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: PDFAusSQLSpeichern schreibt den Inhalt in eine Datei<\/span><\/b><\/p>\n<p>Ob das Feld ein PDF-Dokument enth&auml;lt, entscheidet die Eigenschaft <b>ActualSize<\/b> des Felds. Sie liefert die L&auml;nge in Byte. In unseren Tests lieferte sie sowohl beim Wert <b>NULL<\/b> als auch bei einem Feld mit 0 Byte den Wert 0.<\/p>\n<p>Nur wenn sie gr&ouml;&szlig;er als 0 ist, schreibt die Funktion den Inhalt in die Zieldatei. Dazu verwendet sie einen <b>ADODB.Stream<\/b> und ruft <b>SaveToFile<\/b> mit der Option <b>adSaveCreateOverWrite<\/b> auf. Eine vorhandene Datei &uuml;berschreibt sie dabei.<\/p>\n<p>Die Funktion liefert <b>True<\/b>, wenn sie die Datei geschrieben hat. Andernfalls liefert sie <b>False<\/b>. Der Direktbereich zeigt die Werte in der deutschen Fassung als <b>Wahr<\/b> und <b>Falsch<\/b> an.<\/p>\n<p>Auch hier k&ouml;nnen wir mit dem Parameter <b>strConnection<\/b> eine andere Verbindungszeichenfolge &uuml;bergeben.<\/p>\n<p>Im Direktbereich geben wir den Aufruf in einer Zeile ein. Zur besseren Lesbarkeit haben wir ihn hier umgebrochen:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> PDFAusSQLSpeichern(1, CurrentProject.Path _\r\n    & \"\\export.pdf\")\r\nWahr<\/pre>\n<p>In unseren Tests war die Datei <b>export.pdf<\/b> danach genauso gro&szlig; wie <b>test.pdf<\/b>, und ein Vergleich der Bytes ergab keinen Unterschied. Existiert zur <b>PDFID<\/b> kein Datensatz oder enth&auml;lt das Feld <b>Dateiinhalt<\/b> keine Bytes, liefert der Aufruf <b>Falsch<\/b>. In diesem Fall legt die Funktion die Zieldatei nicht an und &auml;ndert sie nicht.<\/p>\n<p>Beide Funktionen halten die Datei vollst&auml;ndig im Arbeitsspeicher. In unseren Tests haben wir Dateien bis 25 Megabyte fehlerfrei gespeichert und gelesen.<\/p>\n<p>In einer 32-Bit-Anwendung begrenzt der Arbeitsspeicher die Dateigr&ouml;&szlig;e weit unterhalb der 2 Gigabyte des Datentyps. Mit 100 Megabyte gelang das Speichern noch, bei 150 Megabyte trat ein Speicherfehler auf.<\/p>\n<p>Damit die Listings &uuml;bersichtlich bleiben, enthalten sie keine Fehlerbehandlung. Im Produktivcode schlie&szlig;en wir den Stream, das Recordset und die Verbindung in einer Fehlerbehandlung.<\/p>\n<h2>Die Tabelle in Access verkn&uuml;pfen<\/h2>\n<p>F&uuml;r das Formular verkn&uuml;pfen wir die Tabelle mit der Access-Datenbank. Die Prozedur <b>TabelleVerknuepfen<\/b> legt dazu ein Objekt vom Typ <b>TableDef<\/b> mit der ODBC-Verbindung an und setzt die Eigenschaft <b>SourceTableName<\/b> auf <b>dbo.tblPDFs<\/b>.<\/p>\n<p>Danach h&auml;ngt sie es an die Auflistung <b>TableDefs<\/b> an (siehe Listing 5). Eine vorhandene Verkn&uuml;pfung mit diesem Namen l&ouml;scht sie zuvor. Eine lokale Tabelle mit diesem Namen l&ouml;scht sie nicht.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabelleVerknuepfen(<span style=\"color:blue;\">Optional<\/span> ByVal strDatenbank<span style=\"color:blue;\"> As String<\/span> = cstrDatenbank)\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>tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    For Each tdf In db.TableDefs\r\n        <span style=\"color:blue;\">If <\/span>tdf.Name = \"tblPDFs\" And <span style=\"color:blue;\">Len<\/span>(tdf.Connect) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n            db.TableDefs.Delete \"tblPDFs\"\r\n            <span style=\"color:blue;\">Exit For<\/span>\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Next<\/span> tdf\r\n    <span style=\"color:blue;\">Set<\/span> tdf = db.CreateTableDef(\"tblPDFs\")\r\n    tdf.Connect = \"ODBC;DRIVER=ODBC Driver 18 for SQL Server;SERVER=\" & cstrServer & _\r\n        \";DATABASE=\" & strDatenbank & \";Trusted_Connection=Yes;TrustServerCertificate=Yes;\"\r\n    tdf.SourceTableName = \"dbo.tblPDFs\"\r\n    db.TableDefs.Append tdf\r\n    db.TableDefs.Refresh\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: TabelleVerknuepfen verkn&uuml;pft die Tabelle tblPDFs<\/span><\/b><\/p>\n<p>Wie wir Tabellen allgemein per VBA verkn&uuml;pfen, beschreibt der Beitrag <b>SQL Server: Tabellen per VBA verkn&uuml;pfen (www.vbentwickler.de\/485)<\/b>.<\/p>\n<p>Die Verkn&uuml;pfung hei&szlig;t <b>tblPDFs<\/b>. Verkn&uuml;pfen wir die Tabelle von Hand, nennt Access sie <b>dbo_tblPDFs<\/b>. In Access hat das Feld <b>Dateiinhalt<\/b> den DAO-Datentyp <b>dbLongBinary<\/b> (11).<\/p>\n<p>In der Oberfl&auml;che steht daf&uuml;r <b>OLE-Objekt<\/b>. In unseren Beispieldaten zeigt das Datenblatt in jeder Zeile den Eintrag <b>OLE-Objekt<\/b>, auch beim dritten Datensatz, bei dem das Feld <b>Dateiinhalt<\/b> den Wert <b>NULL<\/b> enth&auml;lt (siehe Bild 1). Ob ein PDF-Dokument gespeichert ist, erkennen wir im Datenblatt daher nicht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_520_001.png\" alt=\"Die verkn&uuml;pfte Tabelle tblPDFs im Datenblatt von Access\" width=\"424,9998\" height=\"134,6273\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Die verkn&uuml;pfte Tabelle tblPDFs im Datenblatt von Access<\/span><\/b><\/p>\n<p>Das Listenfeld des Formulars fragt deshalb nur die Felder <b>PDFID<\/b> und <b>Dateiname<\/b> ab, damit Access nicht alle Dokumente &uuml;bertr&auml;gt. Den Inhalt laden wir erst, wenn wir einen Datensatz w&auml;hlen.<\/p>\n<h2>Das Formular<\/h2>\n<p>Das Formular zeigt links die Datens&auml;tze der Tabelle und rechts das gew&auml;hlte PDF-Dokument.<\/p>\n<p>Es besteht aus vier Steuerelementen:<\/p>\n<ul>\n<li><b>lstPDFs:<\/b> ein Listenfeld mit zwei Spalten und der Datensatzherkunft <b>SELECT PDFID, Dateiname FROM tblPDFs ORDER BY PDFID;<\/b>, wobei die erste Spalte die gebundene Spalte ist<\/li>\n<li><b>ctlEdge:<\/b> das Edge-Steuerelement, das das PDF-Dokument anzeigt<\/li>\n<li><b>cmdHinzufuegen:<\/b> die Schaltfl&auml;che <b>PDF hinzuf&uuml;gen<\/b><\/li>\n<li><b>lblHinweis:<\/b> ein Bezeichnungsfeld mit dem Text <b>Zu diesem Datensatz ist kein PDF gespeichert.<\/b><\/li>\n<\/ul>\n<p>Das Formular hat keine eigene Datensatzherkunft. In der Ereignisprozedur zum Ereignis <b>Beim Laden<\/b> blenden wir den Hinweis aus. Er erscheint dadurch nur bei einem Datensatz ohne PDF-Dokument.<\/p>\n<h2>Das Edge-Steuerelement<\/h2>\n<p>Das Edge-Steuerelement zeigt Webseiten und Dokumente mit dem Browser Microsoft Edge an. Es steht nur in Access mit Microsoft 365 zur Verf&uuml;gung. Wir verwenden Access 16.0 mit dem Build 20430. Die Eigenschaft <b>Steuerelementinhalt<\/b> (<b>ControlSource<\/b>) nimmt eine Adresse auf.<\/p>\n<p>F&uuml;r eine lokale Datei stellen wir dem Pfad das Pr&auml;fix <b>https:\/\/msaccess\/<\/b> voran. In unseren Tests zeigte das Steuerelement die Datei im Ordner der Beispieldatenbank an. Es verwendet daf&uuml;r den PDF-Viewer von Edge mit der Symbolleiste (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_520_002.png\" alt=\"Das Formular zeigt das PDF-Dokument des gew&auml;hlten Datensatzes im Edge-Steuerelement\" width=\"700\" height=\"601,1036\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Das Formular zeigt das PDF-Dokument des gew&auml;hlten Datensatzes im Edge-Steuerelement<\/span><\/b><\/p>\n<p>Die Prozedur <b>PDFAnzeigen<\/b> steht im Klassenmodul des Formulars (siehe Listing 6). Sie schreibt das PDF-Dokument des Datensatzes in die Datei <b>export.pdf<\/b> im Ordner der Datenbank und setzt die Eigenschaft <b>ControlSource<\/b> auf die Adresse dieser Datei.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>PDFAnzeigen(ByVal lngPDFID<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>strZiel<span style=\"color:blue;\"> As String<\/span>\r\n    strZiel = CurrentProject.Path & \"\\export.pdf\"\r\n    <span style=\"color:blue;\">If <\/span>PDFAusSQLSpeichern(lngPDFID, strZiel)<span style=\"color:blue;\"> Then<\/span>\r\n        Me.lblHinweis.Visible = <span style=\"color:blue;\">False<\/span>\r\n        Me.ctlEdge.Visible = <span style=\"color:blue;\">True<\/span>\r\n        Me.ctlEdge.ControlSource = \"https:\/\/msaccess\/\" & strZiel\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        Me.lblHinweis.Visible = <span style=\"color:blue;\">True<\/span>\r\n        Me.ctlEdge.Visible = <span style=\"color:blue;\">False<\/span>\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: PDFAnzeigen zeigt das PDF-Dokument eines Datensatzes im Formular an<\/span><\/b><\/p>\n<p>Das Ergebnis des Aufrufs von <b>PDFAusSQLSpeichern<\/b> bestimmt die Anzeige. Liefert er <b>True<\/b>, blenden wir den Hinweis aus und zeigen das Steuerelement an. Liefert er <b>False<\/b>, blenden wir das Steuerelement aus und zeigen den Hinweis an (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_04\/pic_520_003.png\" alt=\"Zu einem Datensatz ohne PDF-Dokument zeigt das Formular einen Hinweis\" width=\"299,9999\" height=\"359,9999\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Zu einem Datensatz ohne PDF-Dokument zeigt das Formular einen Hinweis<\/span><\/b><\/p>\n<p>Das Steuerelement blenden wir mit der Eigenschaft <b>Visible<\/b> aus, die in der Oberfl&auml;che <b>Sichtbar<\/b> hei&szlig;t.<\/p>\n<p>Die Datei <b>export.pdf<\/b> schreiben wir bei jeder Auswahl eines Datensatzes mit PDF-Dokument neu. In unseren Tests schlug das &Uuml;berschreiben nicht fehl, w&auml;hrend das Steuerelement die Datei anzeigte. H&auml;lt eine andere Anwendung die Datei ge&ouml;ffnet und erlaubt keinen Schreibzugriff, l&ouml;st <b>SaveToFile<\/b> einen Fehler aus. Au&szlig;erdem muss der Ordner der Datenbank f&uuml;r den Benutzer beschreibbar sein.<\/p>\n<p>Mehrere Benutzer sollten nicht dasselbe Frontend im selben Ordner verwenden. Andernfalls &uuml;berschreiben sie dieselbe Datei.<\/p>\n<p>Wir rufen die Prozedur im Ereignis <b>Nach Aktualisierung<\/b> des Listenfelds auf. Der Wert des Listenfelds ist die <b>PDFID<\/b>. Haben wir keinen Datensatz gew&auml;hlt, hat er den Wert <b>Null<\/b>.<\/p>\n<p>Die Funktion <b>Nz<\/b> ersetzt ihn durch den Wert 0, und das Formular zeigt in diesem Fall den Hinweis an:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>lstPDFs_AfterUpdate()\r\n    PDFAnzeigen Nz(Me.lstPDFs, 0)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Ein PDF-Dokument aus dem Formular hinzuf&uuml;gen<\/h2>\n<p>Mit der Schaltfl&auml;che <b>PDF hinzuf&uuml;gen<\/b> w&auml;hlen wir eine Datei aus und speichern sie in der Tabelle. Die Funktion <b>PDFAuswaehlen<\/b> &ouml;ffnet dazu den Dateiauswahldialog von Access. Sie steht im selben Standardmodul wie die Funktionen aus den Listings:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>PDFAuswaehlen()<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">With<\/span> Application.FileDialog(msoFileDialogFilePicker)\r\n        .Title = \"PDF ausw&auml;hlen\"\r\n        .AllowMultiSelect = <span style=\"color:blue;\">False<\/span>\r\n        .Filters.Clear\r\n        .Filters.Add \"PDF-Dateien\", \"*.pdf\"\r\n        <span style=\"color:blue;\">If <\/span>.Show<span style=\"color:blue;\"> Then<\/span> PDFAuswaehlen = .SelectedItems(1)\r\n    End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Der Dialog zeigt nur PDF-Dateien an und erlaubt eine einzelne Auswahl. Bricht der Benutzer den Dialog ab, liefert die Funktion eine leere Zeichenfolge.<\/p>\n<p>Die Ereignisprozedur zum Ereignis <b>Beim Klicken<\/b> der Schaltfl&auml;che steht im Klassenmodul des Formulars:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdHinzufuegen_Click()\r\n    <span style=\"color:blue;\">Dim <\/span>strPfad<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n    strPfad = PDFAuswaehlen()\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strPfad) = 0<span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Exit Sub<\/span>\r\n    lngID = PDFInSQLSpeichern(strPfad)\r\n    Me.lstPDFs.Requery\r\n    Me.lstPDFs = lngID\r\n    PDFAnzeigen lngID\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Prozedur speichert die gew&auml;hlte Datei mit <b>PDFInSQLSpeichern<\/b> und aktualisiert die Liste mit <b>Requery<\/b>.<\/p>\n<p>Anschlie&szlig;end w&auml;hlt sie den neuen Datensatz &uuml;ber die zur&uuml;ckgegebene <b>PDFID<\/b> aus und zeigt dessen PDF-Dokument an.<\/p>\n<p>Das Setzen des Listenfelds per Code l&ouml;st das Ereignis <b>Nach Aktualisierung<\/b> nicht aus. Deshalb rufen wir <b>PDFAnzeigen<\/b> selbst auf. Enth&auml;lt die gew&auml;hlte Datei keine Bytes, l&ouml;st <b>PDFInSQLSpeichern<\/b> den Fehler <b>vbObjectError + 1001<\/b> aus. Da die Prozedur keine Fehlerbehandlung enth&auml;lt, zeigt Access einen Laufzeitfehler an.<\/p>\n<h2>Zusammenfassung<\/h2>\n<p>Ein PDF-Dokument gelangt mit <b>ADODB<\/b> in drei Schritten in ein <b>varbinary(max)<\/b>-Feld. Ein <b>ADODB.Stream<\/b> liest die Datei als Bytes, ein <b>ADODB.Command<\/b> &uuml;bergibt sie als Parameter an den <b>INSERT<\/b>, und die neue <b>PDFID<\/b> kommt &uuml;ber <b>SCOPE_IDENTITY()<\/b> zur&uuml;ck.<\/p>\n<p>Zur&uuml;ck auf die Festplatte gelangt der Inhalt &uuml;ber ein <b>ADODB.Recordset<\/b> und einen <b>ADODB.Stream<\/b>. Das Feld erscheint in Access als <b>OLE-Objekt<\/b>.<\/p>\n<p>Das Edge-Steuerelement zeigt die geschriebene Datei an, wenn die Eigenschaft <b>ControlSource<\/b> den Pfad mit dem Pr&auml;fix <b>https:\/\/msaccess\/<\/b> enth&auml;lt.<\/p>\n<p>Die Dateien liegen damit in der Datenbank und sind in der Sicherung der Datenbank enthalten. Daf&uuml;r belegt die Datenbank mit jedem PDF-Dokument mehr Platz.<\/p>\n<p>Je nach Wiederherstellungsmodell w&auml;chst auch das Transaktionsprotokoll. Au&szlig;erdem laden beide Funktionen den Inhalt vollst&auml;ndig in den Arbeitsspeicher.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w&auml;hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel&ouml;scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth&auml;lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf&uuml;r nimmt der Datentyp varbinary(max) Bin&auml;rdaten bis zu einer Gr&ouml;&szlig;e von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit ADODB in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.<\/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,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662026,66042026,44000024,44000021,44000006],"tags":[],"yst_prominent_words":[],"class_list":["post-55000520","post","type-post","status-publish","format-standard","hentry","category-662026","category-66042026","category-Berichte_und_Reporting","category-Entity_Framework","category-SQL_Server_und_Co"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w\u00e4hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel\u00f6scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth\u00e4lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf\u00fcr nimmt der Datentyp varbinary(max) Bin\u00e4rdaten bis zu einer Gr\u00f6\u00dfe von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit ADODB in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Andr\u00e9 Minhorst\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Visual Basic Entwickler - Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"SQL Server: PDFs in varbinary(max)-Feld speichern - Visual Basic Entwickler\" \/>\n\t\t<meta property=\"og:description\" content=\"Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w\u00e4hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel\u00f6scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth\u00e4lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf\u00fcr nimmt der Datentyp varbinary(max) Bin\u00e4rdaten bis zu einer Gr\u00f6\u00dfe von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit ADODB in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-10-18T13:18:05+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"-001-11-30T00:00:00+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"SQL Server: PDFs in varbinary(max)-Feld speichern - Visual Basic Entwickler\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w\u00e4hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel\u00f6scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth\u00e4lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf\u00fcr nimmt der Datentyp varbinary(max) Bin\u00e4rdaten bis zu einer Gr\u00f6\u00dfe von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit ADODB in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#blogposting\",\"name\":\"SQL Server: PDFs in varbinary(max)-Feld speichern - Visual Basic Entwickler\",\"headline\":\"SQL Server: PDFs in varbinary(max)-Feld speichern\",\"author\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"..\\\/fileadmin\\\/_temp_\\\/2026_04\\\/pic_520_001.png\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#articleImage\"},\"datePublished\":\"2026-08-01T00:00:00+00:00\",\"dateModified\":\"-0001-11-30T00:00:00+00:00\",\"inLanguage\":\"de-DE\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#webpage\"},\"articleSection\":\"2026, 4\\\/2026, Berichte und Reporting, Entity Framework, SQL Server und Co.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/vbentwickler.de\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/#listItem\",\"name\":\"2026\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/#listItem\",\"position\":2,\"name\":\"2026\",\"item\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/4\\\/2026\\\/#listItem\",\"name\":\"4\\\/2026\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/4\\\/2026\\\/#listItem\",\"position\":3,\"name\":\"4\\\/2026\",\"item\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/4\\\/2026\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#listItem\",\"name\":\"SQL Server: PDFs in varbinary(max)-Feld speichern\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/#listItem\",\"name\":\"2026\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#listItem\",\"position\":4,\"name\":\"SQL Server: PDFs in varbinary(max)-Feld speichern\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/category\\\/2026\\\/4\\\/2026\\\/#listItem\",\"name\":\"4\\\/2026\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#organization\",\"name\":\"Datenbankentwickler\",\"description\":\"Das Magazin f\\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/cropped-header_vbe-1.png\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#organizationLogo\",\"width\":664,\"height\":225},\"image\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#organizationLogo\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/\",\"name\":\"Andr\\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Andr\\u00e9 Minhorst\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#webpage\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/\",\"name\":\"SQL Server: PDFs in varbinary(max)-Feld speichern - Visual Basic Entwickler\",\"description\":\"Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w\\u00e4hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel\\u00f6scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth\\u00e4lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf\\u00fcr nimmt der Datentyp varbinary(max) Bin\\u00e4rdaten bis zu einer Gr\\u00f6\\u00dfe von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit ADODB in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.\",\"inLanguage\":\"de-DE\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/author\\\/andreminhorst-com\\\/#author\"},\"datePublished\":\"2026-08-01T00:00:00+00:00\",\"dateModified\":\"-0001-11-30T00:00:00+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#website\",\"url\":\"https:\\\/\\\/vbentwickler.de\\\/\",\"name\":\"Datenbankentwickler\",\"description\":\"Das Magazin f\\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.\",\"inLanguage\":\"de-DE\",\"publisher\":{\"@id\":\"https:\\\/\\\/vbentwickler.de\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"SQL Server: PDFs in varbinary(max)-Feld speichern - Visual Basic Entwickler","description":"Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w\u00e4hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel\u00f6scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth\u00e4lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf\u00fcr nimmt der Datentyp varbinary(max) Bin\u00e4rdaten bis zu einer Gr\u00f6\u00dfe von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit ADODB in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.","canonical_url":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#blogposting","name":"SQL Server: PDFs in varbinary(max)-Feld speichern - Visual Basic Entwickler","headline":"SQL Server: PDFs in varbinary(max)-Feld speichern","author":{"@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author"},"publisher":{"@id":"https:\/\/vbentwickler.de\/#organization"},"image":{"@type":"ImageObject","url":"..\/fileadmin\/_temp_\/2026_04\/pic_520_001.png","@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#articleImage"},"datePublished":"2026-08-01T00:00:00+00:00","dateModified":"-0001-11-30T00:00:00+00:00","inLanguage":"de-DE","mainEntityOfPage":{"@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#webpage"},"isPartOf":{"@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#webpage"},"articleSection":"2026, 4\/2026, Berichte und Reporting, Entity Framework, SQL Server und Co."},{"@type":"BreadcrumbList","@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/#listItem","position":1,"name":"Home","item":"https:\/\/vbentwickler.de\/","nextItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/#listItem","name":"2026"}},{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/#listItem","position":2,"name":"2026","item":"https:\/\/vbentwickler.de\/category\/2026\/","nextItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/#listItem","name":"4\/2026"},"previousItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/#listItem","position":3,"name":"4\/2026","item":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/","nextItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#listItem","name":"SQL Server: PDFs in varbinary(max)-Feld speichern"},"previousItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/#listItem","name":"2026"}},{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#listItem","position":4,"name":"SQL Server: PDFs in varbinary(max)-Feld speichern","previousItem":{"@type":"ListItem","@id":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/#listItem","name":"4\/2026"}}]},{"@type":"Organization","@id":"https:\/\/vbentwickler.de\/#organization","name":"Datenbankentwickler","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.","url":"https:\/\/vbentwickler.de\/","logo":{"@type":"ImageObject","url":"https:\/\/vbentwickler.de\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png","@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#organizationLogo","width":664,"height":225},"image":{"@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#organizationLogo"}},{"@type":"Person","@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author","url":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","width":96,"height":96,"caption":"Andr\u00e9 Minhorst"}},{"@type":"WebPage","@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#webpage","url":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/","name":"SQL Server: PDFs in varbinary(max)-Feld speichern - Visual Basic Entwickler","description":"Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w\u00e4hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel\u00f6scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth\u00e4lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf\u00fcr nimmt der Datentyp varbinary(max) Bin\u00e4rdaten bis zu einer Gr\u00f6\u00dfe von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit ADODB in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.","inLanguage":"de-DE","isPartOf":{"@id":"https:\/\/vbentwickler.de\/#website"},"breadcrumb":{"@id":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/#breadcrumblist"},"author":{"@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author"},"creator":{"@id":"https:\/\/vbentwickler.de\/author\/andreminhorst-com\/#author"},"datePublished":"2026-08-01T00:00:00+00:00","dateModified":"-0001-11-30T00:00:00+00:00"},{"@type":"WebSite","@id":"https:\/\/vbentwickler.de\/#website","url":"https:\/\/vbentwickler.de\/","name":"Datenbankentwickler","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.","inLanguage":"de-DE","publisher":{"@id":"https:\/\/vbentwickler.de\/#organization"}}]},"og:locale":"de_DE","og:site_name":"Visual Basic Entwickler - Das Magazin f\u00fcr Datenbankentwickler auf Basis von Visual Studio und Co.","og:type":"article","og:title":"SQL Server: PDFs in varbinary(max)-Feld speichern - Visual Basic Entwickler","og:description":"Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w\u00e4hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel\u00f6scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth\u00e4lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf\u00fcr nimmt der Datentyp varbinary(max) Bin\u00e4rdaten bis zu einer Gr\u00f6\u00dfe von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit ADODB in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.","og:url":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/","og:image":"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png","og:image:secure_url":"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png","article:published_time":"2026-10-18T13:18:05+00:00","article:modified_time":"-001-11-30T00:00:00+00:00","twitter:card":"summary_large_image","twitter:title":"SQL Server: PDFs in varbinary(max)-Feld speichern - Visual Basic Entwickler","twitter:description":"Rechnungen, Angebote und Lieferscheine liegen als PDF-Dateien auf einem Netzlaufwerk, w\u00e4hrend in der Datenbank nur der Pfad zur Datei steht. Wird eine Datei verschoben, umbenannt oder gel\u00f6scht, verweist der Pfad auf keine Datei mehr. Auch ein Backup der Datenbank enth\u00e4lt die Dokumente nicht. Der SQL Server kann die Dateien dagegen in der Datenbank speichern. Daf\u00fcr nimmt der Datentyp varbinary(max) Bin\u00e4rdaten bis zu einer Gr\u00f6\u00dfe von knapp 2 Gigabyte auf, auch ein PDF-Dokument. In diesem Beitrag zeigen wir, wie wir ein PDF-Dokument mit ADODB in ein Feld dieses Datentyps schreiben, wieder in eine Datei auf der Festplatte speichern und in einem Access-Formular im Edge-Steuerelement anzeigen.","twitter:image":"https:\/\/datenbankentwickler.net\/wp-content\/uploads\/2022\/08\/cropped-header_vbe-1.png"},"aioseo_meta_data":{"post_id":"55000520","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"limit_modified_date":false,"created":"2026-10-18 14:16:31","updated":"2026-10-18 14:16:31","ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/vbentwickler.de\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/vbentwickler.de\/category\/2026\/\" title=\"2026\">2026<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/\" title=\"4\/2026\">4\/2026<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tSQL Server: PDFs in varbinary(max)-Feld speichern\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/vbentwickler.de\/"},{"label":"2026","link":"https:\/\/vbentwickler.de\/category\/2026\/"},{"label":"4\/2026","link":"https:\/\/vbentwickler.de\/category\/2026\/4\/2026\/"},{"label":"SQL Server: PDFs in varbinary(max)-Feld speichern","link":"https:\/\/vbentwickler.de\/SQL_Server_PDFs_in_varbinarymaxFeld_speichern\/"}],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000520","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000520"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000520\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000520"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000520"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000520"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000520"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}