Скрипт для сохранения данных varbinary на диск

У меня есть некоторые данные varbinary, хранящиеся в таблице в MS Sql Server 2005. У кого-нибудь есть код SQL, который принимает запрос в качестве входных данных (скажем, запрос гарантирует, что возвращается один столбец varbinary) и выводит байты на диск (один файл на строку?) Я уверен, что это было задано тысячу раз раньше, но Googling придумывает в основном .net-решения. Мне нужно решение SQL.

7 ответов


подход BCP не работает для меня. Байты, которые он записывает на диск, не могут быть десериализованы обратно в объекты .net, которые я сохранил. Это означает, что байты на диске не эквивалентны тому, что хранится. Возможно, BCP пишет какой-то заголовок. Я не уверен.

Я нашел следующий код здесь в нижней части статьи. Он отлично работает! Хотя он предназначен для сохраненных изображений BMP, он работает с любым 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

вы можете использовать BCP, а не T-SQL, но работает хорошо.

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

Я добавляю это, чтобы основываться на ответе JohnOpincar, чтобы другие, кто хочет использовать LinqPad, могли быстрее получить рабочее решение.

/*
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");
}

Я знаю, это старый пост, но я понял, почему следующее не работает и как это исправить:

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

причина в том, что BCP помещает длину префикса в самом начале файла. Это либо 4 байта, либо 8 байтов, зависит от типа данных столбца FileContent (text, ntext, image: 4 varchar (max), varbinary (max) : 8 см.https://msdn.microsoft.com/en-us/library/ms190779.aspx)

используйте двоичный редактор, как в Visual Studio, чтобы удалить префиксные байты, и все работает отлично. :-)


Если у вас есть linqpad, это работает:

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);
}

просто альтернатива. Вы можете использовать бесплатную жабу для SQL server и сохранять ее непосредственно из редактора.

вы можете перейти на их веб-сайтhttps://www.toadworld.com и получите бесплатное ПО там или 30-дневную пробную версию полной версии. Его под скачать и выбрать жабу для SQL server.

enter image description here

вы делаете регулярную инструкцию select в Toad в строке, в которой есть изображение, которое вы хотите сохранить. Когда вы видите результаты, вы можете нажмите на столбец байтовое изображение и справа вы увидите вкладку PDF, если это документ PDF или слева вы видите вкладку изображения. При нажатии на вкладку вы можете увидеть логотип сохранения в нижней части, чтобы сохранить изображение или файл.


SQL предназначен для работы с объектами базы данных, поэтому с его точки зрения ничего другого не существует. Конечно, есть расширенные процедуры, такие как xp_cmdshell которые позволяют взаимодействовать с операционной системой, но они являются собственными расширениями, а не частью T-SQL.

возможно, наиболее близким подходом будет использование атрибута FILESTREAM для двоичных типов SQL Server 2008, которые позволяют хранить некоторые столбцы непосредственно в виде файлов в папке вместо использования база данных:

обзор FILESTREAM

Примечание что хранилище FILESTREAM предназначено для обслуживания больших файлов из базы данных с целью повышения производительности, а не для прямого доступа к файлам (т. е. T-SQL все еще не имеет концепции файловой системы). На мой взгляд, прямой доступ к файловой системе из SQL победит некоторые цели базы данных (в основном имеющие данные, хранящиеся в структурированной путь.)

поэтому я бы рекомендовал следовать совету Дастина и использовать такой инструмент, как BCP или любой другой Дампер данных.