2012-08-30 19 views
7

Estoy intentando exportar un número bastante grande de archivos de imagen, almacenada internamente en una base de datos SQL como datos binarios.Exportación de datos de archivos binarios (imágenes) de SQL a través de un procedimiento almacenado

ser bastante nuevo en la escritura de procedimientos almacenados en SQL, me he encontrado con un par de guías muy útiles sobre cómo esto puede ser archivado, pero me parece que falta algo.

estoy corriendo SQL Server 2008 R2 a nivel local, y yo estoy tratando de escribir los archivos a una carpeta de mi unidad C: \.

Aquí es la parte buisness de lo que tengo hasta ahora:

BEGIN 
DECLARE @cmd VARCHAR(8000) 
DECLARE @result int 

DECLARE curExportBinaryDocs CURSOR FAST_FORWARD FOR 
SELECT 'BCP "SELECT Photograph_Data FROM [ALBSCH Trial].[dbo].[Photograph] WHERE Photograph_ID = ' 
    + CAST(Photograph_ID AS VARCHAR(500)) + '" queryout "' + @OutputFilePath 
    + CAST(Photograph_ID AS VARCHAR(500)) + '.jpg"' + ' -n -T' 
FROM dbo.Photograph 

OPEN curExportBinaryDocs 
FETCH NEXT FROM curExportBinaryDocs INTO @cmd 
WHILE @@FETCH_STATUS = 0 
    BEGIN 
    --PRINT @cmd 
    EXEC @result = xp_cmdshell @cmd   
    FETCH NEXT FROM curExportBinaryDocs INTO @cmd 
    END 
CLOSE curExportBinaryDocs 
DEALLOCATE curExportBinaryDocs 
END 

'@result' siempre está siendo puesto a '1' (fallidos) después de la llamada xp_cmdshell. Todos los nombres/campos de la tabla son correctos, así que sospecho que hay algo mal con mi llamada BCP, pero no estoy seguro de qué probar a continuación.

Cualquier ayuda o consejo sería muy bienvenido.

+0

¿Cómo está ejecutando el SQL? El SQL se ejecuta con las credenciales de un usuario ... ¿Tiene ese usuario derechos para crear archivos en la carpeta de salida? –

+0

Estoy iniciando sesión en el servidor SQL utilizando mi nombre de usuario de windows habitual y la autenticación de Windows. He logrado que una solución funcione usando el método descrito aquí: http://stackoverflow.com/questions/1366544/how-to-export-image-field-to-file pero si es posible me gustaría llegar a el fondo del problema que estoy teniendo con mi método original, ¡solo por tranquilidad! – ChrisMurray

+0

Creo que lo que estás haciendo está un poco mal. ¿Conoce la "base de datos de habilitación de flujo de archivos" de SQL Server? Le permite almacenar BLOBs en la Unidad de Disco Duro mientras los BLOB aún son mantenidos por su Servidor SQL. Después de enviar estos BLOB a la unidad, su aplicación solo necesita realizar una consulta en su base de datos y obtener el objeto. Además, usar el cursor no es algo bueno (es lento). – gotqn

Respuesta

5

Bueno, en primer lugar .. (y lo siento por eso;)) DON "T .. utilizar cursores y lo siento por las tapas ...

uno de los más cosas más malo sobre cursores que están puede bloquear su mesa. lo que siempre hago para estos fines (y que es bastante rápido), yo uso un bucle for .. como esta

declare @totrow int 
     , @currow int 
     , @result int 
     , @nsql nvarchar(max) 

declare @sqlStatements table (
    Id int identity(1, 1) 
, SqlStatement varchar(max) 
) 
insert 
into @sqlStatements 
select 'QUERY PART' 
from table 

set @totrow = @@rowcount 
set @currow = 1 
while @totrow > 0 and @currow <= @totrow 
begin 
    select @nsql = SqlStatement 
    from @SqlStatements 
    where Id = @currow 

    exec @result = xp_cmdshell @nsql 

    set @currow = @currow + 1 
end 

para la siguiente parte, hace el proceso de SQL Server tiene suficiente permiso para escribe en la unidad c: también, mira en el panel de mensajes cuando ejecutas tu código, ¿quizás puedes encontrar algo allí?

Lo que también puede hacer, intente ejecutarlo manualmente. Solo obtenga un enunciado BCP y ejecútelo con xp_cmdshell. ¿Da algún error?

+0

Gracias Marcar Había pasado de esto después de obtener una solución diferente para trabajar, pero habiendo visto sus comentarios fui y volví a mirar. Después de modificar mi código para evitar usar el cursor y luego luchar con los permisos de BCP y las comillas, ahora lo tengo funcionando bien. Muchas gracias. Yo votaría su respuesta, pero aún no tengo suficientes representantes :) – ChrisMurray

+0

Me alegro de escuchar que me ayudó :) –

+0

@MarkKremers mientras tiene los cursores correctos, los bucles se implementan mediante cursores y los cursores proporcionan más control sobre el rendimiento, por lo que aunque los bucles funcionan mejor que los cursores adecuados: http://sqlblog.com/blogs/aaron_bertrand/archive/2012/01/26/the-fallacy-that-a-while-loop-isn-ta- cursor.aspx – ConstantineK

6

Aquí es mi último archivo de procedimiento de trabajo y el formato. No pude encontrar los detalles más precisos de los comandos BCP, las configuraciones de permisos y los formatos de archivos de formato en un solo lugar, así que tal vez esto sea útil para alguien.

CREATE PROCEDURE [dbo].[ImgExport] 
    @OutputFilePath VARCHAR(500) = 'C:\SQLTest\ ' 
AS 
BEGIN 
    DECLARE @totrow int 
    DECLARE @currow int 
    DECLARE @result int 
    DECLARE @nsql nvarchar(4000) 
    DECLARE @sqlStatements table (ID int IDENTITY(1, 1), SqlStatement varchar(max)) 

    INSERT 
    INTO @sqlStatements 
    SELECT 'BCP "SELECT Photograph_Data FROM [ALBSCH_Trial].[dbo].[Photograph] WHERE Photograph_ID = ''' 
    + CAST(Photograph_ID AS VARCHAR(500)) + '''" queryout ' + @OutputFilePath 
    + CAST(Photograph_ID AS VARCHAR(500)) + '.jpg -S localhost\SQLEXPRESS2008 -T -f C:\SQLTest\Images.fmt' 
    FROM dbo.Photograph 

    SET @totrow = @@ROWCOUNT 
    SET @currow = 1 
    WHILE @totrow > 0 and @currow <= @totrow 
    BEGIN 
     SELECT @nsql = SqlStatement 
     FROM @sqlStatements 
     WHERE ID = @currow 
     EXEC @result = xp_cmdshell @nsql 
     SET @currow = @currow + 1 
    END 
END  

archivo de formato:

9.0 
1 
1  SQLBINARY  0  0  "\t"  1  Photograph_Data         "" 

espero que ayude a alguien.

+1

Hola, @ChrisMurray, dado que el contenido de esta columna es de datos binarios/brutos, puedes evitar el archivo de formato al proporcionar el indicador '-N' a la línea de comando BCP, es decir:' BCP 'SELECCIONAR datos FROM [ Fotografía] DONDE ID = 123; " queryout "123.jpg" -S localhost \ SQLEXPRESS2008 -T -N' –

+0

No pude producir Tifs que podría abrir utilizando -N en lugar del archivo de formateo. Aparentemente porque estaba agregando algunos bytes de encabezado de algún tipo. Si deja fuera todas las opciones de formateo en su primera llamada BCP, le solicitará los parámetros de formateo. Acepté los valores predeterminados a excepción de los bytes del encabezado que configuré a cero. Luego, me impulsó a guardar el archivo al que luego hice referencia en mis otras solicitudes de BCP utilizando el indicador -f. – user2027080

Cuestiones relacionadas