convertir - varbinary sql server
Script para guardar datos varbinary en el disco (7)
Puede usar BCP, no T-SQL, pero funciona bien.
BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:/file.txt" -T
Tengo algunos datos varbinary almacenados en una tabla en MS Sql Server 2005. ¿Alguien tiene código SQL que toma una consulta como entrada (digamos que la consulta garantiza que se devuelve una sola columna de varbinary) y los resultados de los bytes en el disco (un archivo por fila?) Estoy seguro de que esto se ha preguntado miles de veces antes, pero Google ofrece soluciones principalmente .net. Quiero una solución SQL.
SQL está diseñado para trabajar con objetos de base de datos, por lo que desde su punto de vista, cualquier otra cosa no existe. Claro, hay procedimientos extendidos como xp_cmdshell
que le permiten interactuar con el sistema operativo, pero son extensiones propietarias y no son parte de T-SQL.
Tal vez el enfoque más cercano sería usar el atributo FILESTREAM para los tipos binarios de SQL Server 2008, que permiten almacenar algunas columnas directamente como archivos en una carpeta en lugar de usar la base de datos:
Tenga en cuenta que el almacenamiento de FILESTREAM está diseñado para mantener archivos grandes fuera de la base de datos con el fin de aumentar el rendimiento y no para permitir el acceso directo a archivos (es decir, T-SQL aún no tiene el concepto de sistema de archivos). En mi opinión, el acceso directo al sistema de archivos desde SQL anulará algunos de los propósitos de una base de datos (principalmente tener datos almacenados de forma estructurada).
Así que recomendaría seguir los consejos de Dustin y usar una herramienta como BCP o cualquier otro descargador de datos.
El enfoque BCP no funciona para mí. Los bytes que escribe en el disco no se pueden deserializar de nuevo a los objetos .net que almacené. Esto significa que los bytes en el disco no son equivalentes a lo que está almacenado. Quizás BCP está escribiendo algún tipo de encabezado. No estoy seguro.
Encontré el siguiente código aquí en la parte inferior del artículo. ¡Funciona genial! Aunque fue diseñado para imágenes BMP almacenadas, funciona con cualquier 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
Sé que es una publicación anterior, pero descubrí por qué lo siguiente no funciona y cómo solucionarlo:
BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:/file.JPG" -T -N
El motivo es bcp poner Longitud de prefijo al principio del archivo. Es de 4 bytes u 8 bytes, depende del tipo de datos de la columna FileContent (texto, ntext, imagen: 4 varchar (max), varbinary (max): 8 Consulte https://msdn.microsoft.com/en-us /library/ms190779.aspx )
Use un editor binario, como el de Visual Studio, para eliminar los bytes de prefijo, y todo funciona perfectamente. :-)
Si tienes linqpad, esto funciona:
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);
}
Estoy agregando esto para construir sobre la respuesta de JohnOpincar, para que otros que quieran usar LinqPad puedan obtener una solución más rápida.
/*
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");
}