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 saca los bytes al disco (¿un archivo por fila?). Estoy seguro de que esto se ha preguntado miles de veces antes, pero Google busca soluciones en su mayoría .NET. Quiero una solución SQL.Script para guardar datos varbinary en el disco
Respuesta
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 here 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
Puede usar BCP, no T-SQL, pero funciona bien.
BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.txt" -T
Hola Dustin - Pude usar el comando para generar un archivo, pero no creo que esté funcionando correctamente. Los datos son un objeto .net serializado. Sé que los datos están almacenados correctamente porque tengo procesos que operan con esos datos desde .net. Sin embargo, cuando trato de deserializar recibo un error, lo que significa que los bytes no están escritos correctamente. ¿Pensamientos? Si el comando genera un único valor varbinary (max), ¿se escriben los bytes reales en el disco o el proceso incluye encabezados, etc.? – SFun28
El uso de la opción -N parece que esto funcione correctamente –
Usar las siguientes opciones cuando se le solicite: - Introducir el tipo de almacenamiento de archivos de campo XXX [varbinary (max)]:
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.
Quizás el enfoque más cercano estaría utilizando el atributo FILESTREAM para este tipo de binarios de SQL Server 2008, que permiten el almacenamiento de algunas columnas directamente como archivos en una carpeta en lugar de utilizar la base de datos:
Observe que el almacenamiento FILESTREAM está diseñado para mantener archivos grandes fuera de la base de datos para 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 de SQL frustrará algunos de los propósitos de una base de datos (principalmente tener datos almacenados de una manera estructurada).
Así que recomendaría seguir los consejos de Dustin y utilizar una herramienta como BCP o cualquier otro descargador de datos.
sé que es una entrada antigua, pero me di cuenta de por qué el siguiente no funciona y cómo solucionarlo:
BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.JPG" -T -N
La razón es BCP puso longitud de prefijo en el comienzo mismo de el archivo. Es bien 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)
Utilice un editor binario, como el uno en Visual Studio, para eliminar los bytes de prefijo, y todo funciona perfectamente. :-)
Si ha 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);
}
Pitch Perfect .. – irfandar
esto funciona ...? realmente, entonces 'var context = this' buscará automáticamente su instancia de servidor sql, iniciará sesión, encontrará la base de datos correcta, que tiene un esquema donde existe la tabla de imágenes ... ¡Nunca se supo que LinqPad era tan inteligente! –
¿Alguna vez lo usaste? No parece así. Supongo que irfandar y yo solo lo estamos imaginando. – JohnOpincar
estoy añadiendo esto a construir sobre la respuesta de JohnOpincar, de modo que otras personas que quieren utilizar LINQPad puede obtener una solución de trabajo más rápido.
/*
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");
}
- 1. Guardar nsdate en el disco
- 2. Guardar NSMutableArray en el disco
- 3. Guardar NSCache contenido en disco
- 4. Guardar un DynamicMethod en el disco
- 5. Guardar clasificador en el disco en scikit-learn
- 6. Buffers de protocolo; guardar datos en el disco y cargar el número de vuelta
- 7. ¿Es posible guardar un ensamblaje dinámico en el disco?
- 8. ¿Cómo pruebo la unidad para guardar el archivo en el disco?
- 9. Extensión de Chrome: cómo guardar un archivo en el disco
- 10. guardar un archivo (de corriente) en el disco usando C#
- 11. Guardar/Escribir NSMutableArray de los objetos en el disco?
- 12. Manera eficiente de guardar datos en el disco mientras se ejecuta una tarea de cálculo intensivo
- 13. ¿Qué datos pueden almacenarse en el tipo de datos varbinary de SQL Server?
- 14. ¿Necesitamos usar MappedByteBuffer.force() para vaciar datos en el disco?
- 15. Guardar una cadena de Base64 en el disco como un binario usando PHP
- 16. Estrategias para verificar ISNULL en campos varbinary?
- 17. ¿Cómo se persisten los datos en el disco desde .NET?
- 18. Guardar datos en ejecutable
- 19. ¿Cómo guardar un archivo XML en un disco con python?
- 20. Cómo script VARBINARY para copiarlo de una base de datos a otra usando una secuencia de comandos?
- 21. Bash: ejecutar script en el archivo de guardar?
- 22. Varbinary vs Blob en MySQL
- 23. Guardar datos en el almacenamiento externo
- 24. Ejecutar script de implementación en eclipse guardar
- 25. Cambiar el tamaño y guardar una imagen en el disco en Monotouch
- 26. Elisp: cómo guardar datos en un archivo?
- 27. ¿Cómo almaceno datos JSON en un disco?
- 28. Entity framework y VARBINARY
- 29. VarBinary vs Image SQL Server ¿Tipo de datos para almacenar datos binarios?
- 30. Guardar datos de entrada en el botón localStorage on click
Para ejecutar esto, es posible que deba habilitar los procedimientos de automatización OLE https://msdn.microsoft.com/en-us/library/ms191188.aspx. –