wake-up-neo.net

Skript zum Speichern varbinary-Daten auf der Festplatte

Ich habe einige varbinary-Daten in einer Tabelle in MS SQL Server 2005 gespeichert. Hat jemand SQL-Code, der eine Abfrage als Eingabe akzeptiert (sagen wir, die Abfrage gewährleistet, dass eine einzige Spalte von varbinary zurückgegeben wird) und gibt die Bytes auf die Festplatte (eine Datei) aus pro row?) Ich bin mir sicher, dass das schon tausendmal gefragt wurde, aber Googling hat meistens .net-Lösungen. Ich möchte eine SQL-Lösung.

25
SFun28

Der BCP-Ansatz funktioniert für mich nicht. Die Bytes, die auf die Festplatte geschrieben werden, können nicht in die von mir gespeicherten .net-Objekte deserialisiert werden. Dies bedeutet, dass die Bytes auf der Festplatte nicht den gespeicherten Daten entsprechen. Vielleicht schreibt BCP eine Art Header. Ich bin mir nicht sicher. 

Ich habe den folgenden Code hier am Ende des Artikels gefunden. Es funktioniert super! Obwohl es für gespeicherte BMP - Bilder gedacht war, funktioniert es mit jedem Varbinary.

DECLARE @SQLIMG VARCHAR(MAX),
    @IMG_PATH VARBINARY(MAX),
    @TIMESTAMP VARCHAR(MAX),
    @ObjectToken INT

DECLARE IMGPATH CURSOR FAST_FORWARD FOR 
        SELECT csl_CompanyLogo from mlm_CSCompanySettingsLocalizations

OPEN IMGPATH 

FETCH NEXT FROM IMGPATH INTO @IMG_PATH 

WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @TIMESTAMP = 'd:\' + replace(replace(replace(replace(convert(varchar,getdate(),121),'-',''),':',''),'.',''),' ','') + '.bmp'

        PRINT @TIMESTAMP
        PRINT @SQLIMG

        EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT
        EXEC sp_OASetProperty @ObjectToken, 'Type', 1
        EXEC sp_OAMethod @ObjectToken, 'Open'
        EXEC sp_OAMethod @ObjectToken, 'Write', NULL, @IMG_PATH
        EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL, @TIMESTAMP, 2
        EXEC sp_OAMethod @ObjectToken, 'Close'
        EXEC sp_OADestroy @ObjectToken

        FETCH NEXT FROM IMGPATH INTO @IMG_PATH 
    END 

CLOSE IMGPATH
DEALLOCATE IMGPATH
35
SFun28

Sie können BCP verwenden, nicht T-SQL, funktioniert jedoch gut.

BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.txt" -T
12
Dustin Laine

Ich füge dies hinzu, um auf JohnOpincars Antwort aufzubauen, damit andere, die LinqPad verwenden möchten, schneller eine funktionierende Lösung erhalten können.

/*
This LinqPad script saves data stored in a VARBINARY field to the specified folder.
1. Connect to SQL server and select the correct database in the connection dropdown (top right)
2. Change the Language to C# Program
3. Change "Attachments" to the name of your table that holds the VARBINARY data
4. Change "AttachmentBuffer" to the name of the field that holds the data
5. Change "Id" to the unique identifier field name
6. Change "1090" to the identity of the record you want to save
7. Change the path to where you want to save the file. Make sure you choose the right extension.

Notes: Windows 10 may give you "Access Denied" error when trying to save directly to C:\. Rather save to a subfolder.
*/

void Main()
{
    var context = this;
    var query = 
        from ci in context.Attachments
        where ci.Id == 1090
        select ci.AttachmentBuffer
    ;
    byte[] result = query.Single().ToArray();
    File.WriteAllBytes(@"c:\DEV\dumpfile.xlsx", result);
    Console.WriteLine("Done");
}
10
Atron Seige

Ich weiß, dass es ein alter Beitrag ist, aber ich habe herausgefunden, warum das Folgende nicht funktioniert und wie man es reparieren kann:

BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.JPG" -T -N

Der Grund ist bcp put Prefix Length ganz am Anfang der Datei. Es ist entweder 4 Byte oder 8 Byte, abhängig vom Datentyp der FileContent-Spalte (Text, Ntext, Bild: 4 varchar (max), varbinary (max): 8 Siehe https://msdn.Microsoft.com/de -us/library/ms190779.aspx )

Verwenden Sie einen binären Editor wie den in Visual Studio, um die Präfix-Bytes zu entfernen, und alles läuft einwandfrei. :-)

4
Sean Zhu

Nur eine Alternative. Sie können die Freeware Toad for SQL Server verwenden und direkt aus dem Editor heraus speichern.

Sie können auf deren Website https://www.toadworld.com gehen und dort die Freeware oder eine 30-Tage-Testversion der Vollversion erhalten. Es ist unter Downloaden und wählen Sie Toad for SQL Server.

 enter image description here

In Toad führen Sie in der Zeile, in der das Bild gespeichert werden soll, eine reguläre Auswahlanweisung aus. Wenn Sie die Ergebnisse sehen, können Sie auf die Byte-Bildspalte klicken. Rechts erscheint die Registerkarte PDF Dies ist ein PDF -Dokument oder auf der linken Seite wird eine Registerkarte Bild angezeigt. Wenn Sie auf die Registerkarte klicken, können Sie das Speichern-Logo unten sehen, um das Bild oder die Datei zu speichern.

2
Vilhelm

Wenn Sie Linqpad haben, funktioniert das:

void Main()
{
    var context = this;
    var query = 
        from ci in context.Images
        where ci.ImageId == 10
        select ci.Image
    ;
    var result = query.Single ();
    var bytes = Convert.FromBase64String(result);
    File.WriteAllBytes(@"c:\image.bmp", bytes);
}
2
JohnOpincar

SQL ist so konzipiert, dass es mit Datenbankobjekten arbeitet, sodass aus seiner Sicht nichts anderes existiert. Sicher, es gibt erweiterte Verfahren wie xp_cmdshell, mit denen Sie mit dem Betriebssystem interagieren können, aber sie sind proprietäre Erweiterungen und nicht Teil von T-SQL.

Am nächsten wäre es vielleicht, das FILESTREAM-Attribut für binäre Typen von SQL Server 2008 zu verwenden, mit dem einige Spalten direkt als Dateien in einem Ordner gespeichert werden können, anstatt die Datenbank zu verwenden:

FILESTREAM-Übersicht

Note, dass der FILESTREAM-Speicher dafür ausgelegt ist, große Dateien außerhalb der Datenbank zu speichern, um die Leistung zu erhöhen, und nicht, um direkten Zugriff auf Dateien zuzulassen (dh T-SQL hat noch keine Konzept eines Dateisystems). Meiner Meinung nach wird ein direkter Zugriff auf das Dateisystem von SQL einige der Zwecke einer Datenbank zunichte machen (hauptsächlich, wenn Daten strukturiert gespeichert werden).

Daher würde ich empfehlen, den Ratschlägen von Dustin zu folgen und ein Werkzeug wie BCP oder einen anderen Datendumper zu verwenden.

0