In my last post I demonstrated how to use SSIS to load binary files into a SQL Server 2005 VARBINARY(MAX) column, http://jahaines.blogspot.com/2009/10/ssis-importing-binary-files-into.html. This post will focus on recreating the binary documents on the file system. I will be using a combination of TSQL and the BCP utility to perform the export, http://msdn.microsoft.com/en-us/library/ms162802.aspx. I will be using the same table and data from the last post. I will start by creating the TSQL to dynamically create a BCP command.
Below is the stored procedure I will use to export the data. You will see that I have decided to use a cursor to process all documents. The procedure also accepts a DocID, which limits the export to a single document. A cursor is fine here because we are limited to executing a single BCP command; however, you could create an SSIS package that executes the stored procedure across multiple streams, if you need parallel processing.
CREATE PROCEDURE usp_ExportBinaryFiles(
@DocID INT = NULL,
@OutputFilePath VARCHAR(500) = 'C:\'
)
AS
BEGIN
DECLARE @sql VARCHAR(8000)
IF @DocID IS NULL --Open Cursor to export all images
BEGIN
DECLARE curExportBinaryDocs CURSOR FAST_FORWARD FOR
SELECT 'BCP "SELECT Doc FROM [tempdb].[dbo].[Documents] WHERE DocId ='
+ CAST(DocId AS VARCHAR(5)) + '" queryout ' + @OutputFilePath
+ DocName + '.' + DocType + ' -S A70195\Dev -T -fC:\Documents\Documents.fmt'
FROM dbo.Documents
OPEN curExportBinaryDocs
FETCH NEXT FROM curExportBinaryDocs INTO @sql
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT @sql
EXEC xp_cmdshell @sql,NO_OUTPUT
FETCH NEXT FROM curExportBinaryDocs INTO @sql
END
CLOSE curExportBinaryDocs
DEALLOCATE curExportBinaryDocs
END
ELSE --Export a single image
BEGIN
SELECT @sql = 'BCP "SELECT Doc FROM [tempdb].[dbo].[Documents] WHERE DocId ='
+ CAST(DocId AS VARCHAR(5)) + '" queryout ' + @OutputFilePath
+ DocName + '.' + DocType + ' -S A70195\Dev -T -fC:\Documents\Documents.fmt'
FROM dbo.Documents
WHERE DocID = @DocID
--PRINT @sql
EXEC xp_cmdshell @sql,NO_OUTPUT
END
END
GO
The above stored procedure dynamically builds a BCP command. Currently the stored procedure has two main parameters, DocID and OutputFilePath. DocID is used when you want to export a single row, if no value is supplied the stored procedure will export all documents. The outputFilePath is the directory where the files will be exported. You will note that I have hard coded my server name and format file path. You can add additional parameters if you need these attributes to be dynamic. The next item on my list is to actually create the format file. Create a .fmt file somewhere on your file system. I put mine in the same folder as my other documents. Copy the code below into the format file.
9.0
1
1 SQLBINARY 0 0 "" 1 Doc ""
You may be asking yourself, why the format file looks skimpy, or is lacking content. The format file is lacking content because it only has what we need. All we need in the format file is the VARBINARY(MAX) column and its data type. You can find more info on format files here, http://msdn.microsoft.com/en-us/library/ms191516.aspx.
Once the format file is in place, we can execute our stored procedure to process all documents.
EXEC dbo.usp_ExportBinaryFiles @OutputFilePath = 'C:\Documents\BCP_Out\'
That’s it! It is that easy to output VARBINARY data onto the file system. SQL Server 2005 has a slue of tools that make working with binary data very simplistic. I hope that you have learned something new. Please stay tuned, as I plan to focus more on TSQL concepts and performance considerations.
Until next time happy coding.
