Estoy respondiendo esta pregunta porque descubrí una manera de hacerlo más rápido.
El uso de la utilidad bcp (programa de copia masiva) desde la línea de comandos conserva el formato de archivo nativo y es muy rápido. Los archivos de salida también se pueden escribir en un directorio local. Además, los formatos de archivo se pueden personalizar si es necesario.
Editar:Agregar una versión más detallada de la respuesta con el código que usé.
1) Establezca los permisos necesarios para ejecutar xp_cmdshell
.
EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
EXEC sp_configure 'xp_cmdshell',1
GO
RECONFIGURE;
GO
2) Exporte el archivo de formato para la tabla usando bcp
bcp schemaname.tablename format nul -T -n -f format_file_tablename.fmt
Reemplazar -T
con -S servername -d databasename -U username -P password
si no se conecta a la base de datos usando seguridad integrada.
3) Después de una exportación exitosa del archivo de formato, edítelo para eliminar todas las demás columnas excepto la image
o varbinary
columna.
Inicialmente, el archivo de formato se veía así.
11.0
17
1 SQLNCHAR 2 200 "" 1 Name SQL_Latin1_General_CP1_CI_AS
2 SQLNCHAR 2 1000 "" 2 Description SQL_Latin1_General_CP1_CI_AS
3 SQLUNIQUEID 1 16 "" 3 GUID ""
4 SQLBIT 1 1 "" 4 Enabled ""
5 SQLNCHAR 2 600 "" 5 ClassType SQL_Latin1_General_CP1_CI_AS
6 SQLINT 0 4 "" 6 PartitionID ""
7 SQLBIT 1 1 "" 7 Protected ""
8 SQLDATETIME 1 8 "" 8 LastModifiedTime ""
9 SQLINT 0 4 "" 9 LastModifiedByID ""
10 SQLINT 0 4 "" 10 ImageType ""
11 SQLBIT 1 1 "" 11 Template ""
12 SQLINT 0 4 "" 12 ObjectID ""
13 SQLBINARY 8 0 "" 13 Image --column of interest ""
14 SQLINT 0 4 "" 14 ParentId ""
15 SQLNCHAR 2 600 "" 15 ParentClassType SQL_Latin1_General_CP1_CI_AS
16 SQLBIT 1 1 "" 16 IsPrimary ""
17 SQLDATETIME 1 8 "" 17 ImageCaptureDate ""
Edité el archivo como se muestra a continuación.
11.0
1
1 SQLBINARY 0 0 "" 1 Image ""
4) Luego tuve que recorrer las filas de la tabla para extraer la columna de imagen en cada fila como un archivo. Usé una temp table
para este propósito.
IF OBJECT_ID('dbo.tmp_for_picture', 'U') IS NOT NULL
DROP TABLE tmp_for_picture
GO
select
row_number() over(order by parentid) as rownum
,i.image as image_column
,i.parentid
,replace(p.name,',','') as picture_file_name
,i.name
into tmp_for_picture
from Images i
join personnel p on p.ObjectID = i.ParentId
GO
declare @cnt int
declare @i int
declare @filename varchar(512)
declare @extension varchar(20)
declare @sql varchar(4000)
set @cnt = (select count(*) from Images i join personnel p on p.ObjectID = i.ParentId)
set @i = 1
set @extension = '.jpeg' --or extract the extension from a column in the table if available
while @i <= @cnt
begin
--print @i
set @filename = (select picture_file_name from tmp_for_picture where rownum = @i)
set @sql = 'bcp "select image_column from tmp_for_picture where rownum = '+str(@i)+'" queryout "F:\pictures\'[email protected][email protected]+'" -f formatfile.fmt -S servername -d databasename -T'
--print @sql
exec xp_cmdshell @sql
set @i = @i+1
end
GO
Los pasos descritos anteriormente se pueden utilizar para extraer cualquier tipo de archivo de imagen/varbinary (almacenado como pdf, docx, etc.) de la base de datos.