У меня есть некоторые varbinary данные, хранящиеся в таблице в MS Sql Server 2005. У кого-нибудь есть код SQL, который принимает запрос как ввод (скажем, запрос гарантирует, что возвращается один столбец varbinary) и выводит байты на диск (по одному файлу в строке?) Я уверен, что это было задано тысячу раз раньше, но Googling придумывает в основном решения .net. Я хочу решение SQL.
Script для сохранения данных varbinary на диск
Ответ 1
Подход 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
Ответ 2
Вы можете использовать BCP, а не T-SQL, но хорошо работает.
BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.txt" -T
Ответ 3
Я знаю это старое сообщение, но я понял, почему следующее не работает и как его исправить:
BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.JPG" -T -N
Причина в том, что bcp помещает префиксную длину в самом начале файла. Это либо 4 байта, либо 8 байтов, зависит от типа данных столбца FileContent (текст, ntext, изображение: 4 varchar (max), varbinary (max): 8 Обратитесь к https://msdn.microsoft.com/en-us/library/ms190779.aspx)
Используйте двоичный редактор, например, тот, что в Visual Studio, для удаления префиксных байтов, и все работает отлично.: -)
Ответ 4
Я добавляю это, чтобы построить ответ 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");
}
Ответ 5
Просто альтернатива. Вы можете использовать бесплатную Toad для SQL Server и сохранять непосредственно из редактора.
Ответ 6
Если у вас есть 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);
}
Ответ 7
SQL предназначен для работы с объектами базы данных, поэтому с его точки зрения ничего другого не существует. Конечно, существуют расширенные процедуры, такие как xp_cmdshell
, которые позволяют вам взаимодействовать с операционной системой, но они являются проприетарными расширениями, а не частью T-SQL.
Возможно, самым близким подходом будет использование атрибута FILESTREAM для двоичных типов SQL Server 2008, которые позволяют хранить некоторые столбцы непосредственно в виде файлов в папке вместо использования базы данных:
Примечание, что хранилище FILESTREAM предназначено для поддержки больших файлов из базы данных, чтобы повысить производительность, а не для прямого доступа к файлам (т.е. T-SQL по-прежнему не имеет концепция файловой системы). Я полагаю, прямой доступ к файловой системе из SQL приведет к поражению некоторых целей базы данных (в основном, имеющих данные, структурированные).
Поэтому я бы посоветовал следовать совету Дастина и использовать инструмент, такой как BCP или любой другой демпфер данных.