Скрипт для сохранения varbinary данных на диск - PullRequest
31 голосов
/ 30 октября 2010

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

Ответы [ 7 ]

35 голосов
/ 03 ноября 2010

Подход 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
13 голосов
/ 30 октября 2010

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

BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.txt" -T
12 голосов
/ 10 ноября 2016

Я добавляю это, чтобы основываться на ответе 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");
}
6 голосов
/ 22 декабря 2015

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

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

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

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

3 голосов
/ 29 января 2016

Если у вас есть 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);
}
2 голосов
/ 13 октября 2016

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

Вы можете зайти на их сайт https://www.toadworld.com и получить там бесплатное программное обеспечение или 30-дневную пробную версию полной версии. В разделе «Скачать» выберите «Жаба для SQL-сервера».

enter image description here

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

0 голосов
/ 31 октября 2010

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

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

Обзор FILESTREAM

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

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

...