Learn more about SQL Server tools

mssqltips logo

Tutorials          DBA          Dev          BI          Career          Categories          Webcasts          Scripts          Today's Tip          Join

Tutorials      DBA      Dev      BI      Categories      Webcasts

DBA    Dev    BI    Categories


Simple Image Import and Export Using T-SQL for SQL Server

By:   |   Updated: 2017-07-17   |   Comments (15)   |   Related: More > Import and Export


The requirement is to be able to either import or export an image (binary) file to or from SQL Server without using third party tools and without using the BCP (Bulk Copy Program) utility or Integration Services (SSIS). The goal is to use only the database engine capabilities using simple T-SQL code.


The solution involves a table that stores image data and the programming of two stored procedures. The first procedure does the import of the image file into a SQL table and the second procedure does the export of the image from a SQL table.

Both procedures have the same three parameters:

  • @PicName - This is a unique key that defines the picture record. Note that the import action assumes that this is a new picture so only inserting is allowed.
  • @ImageFolderPath - For the export, this is the folder where the file would be saved.  For the import, this is the folder where the file is imported from. Note this folder should exist on your SQL Server and not on a client machine.
  • @Filename - For the export, it is the name of the output file and for the import it is the name of the input file.

The import procedure uses the OPENROWSET function combined with the BULK option to import the file into SQL Server. Since this comes from a parameter, the statement is executed dynamically using the SQL EXEC function using dynamic SQL.

The export procedure uses SQL Server's OLE Automation Procedures ability to write the selected image data stored in a large varbinary variable found by selecting the data by querying the pictures table by the picture name and then saving it to a file in the OS by using the internal sp_OAMethod system procedure.

Create Table and Stored Procedures

In order to store the image file inside SQL Server, I have a simple table called dbo.Pictures containing the picture name, the picture file name and the binary data of the picture itself.

Here is the Pictures table creation script:

   , picFileName NVARCHAR (100)
   , PictureData VARBINARY (max)

Please note that as a preliminary action the OLE Automation Procedures option must be set and active on the SQL Server for the image export action and the BulkAdmin privilege should be given to the executor of the image import action.

Here is the T-SQL script needed for those privileges:

Use master
EXEC sp_configure 'show advanced options', 1; 
EXEC sp_configure 'Ole Automation Procedures', 1; 
ALTER SERVER ROLE [bulkadmin] ADD MEMBER [Enter here the Login Name that will execute the Import] 

Image Import Stored Procedure

CREATE PROCEDURE dbo.usp_ImportImage (
     @PicName NVARCHAR (100)
   , @ImageFolderPath NVARCHAR (1000)
   , @Filename NVARCHAR (1000)
   DECLARE @Path2OutFile NVARCHAR (2000);
   DECLARE @tsql NVARCHAR (2000);
   SET @Path2OutFile = CONCAT (
         , @Filename
   SET @tsql = 'insert into Pictures (pictureName, picFileName, PictureData) ' +
               ' SELECT ' + '''' + @PicName + '''' + ',' + '''' + @Filename + '''' + ', * ' + 
               'FROM Openrowset( Bulk ' + '''' + @Path2OutFile + '''' + ', Single_Blob) as img'
   EXEC (@tsql)

Image Export Stored Procedure

CREATE PROCEDURE dbo.usp_ExportImage (
   @PicName NVARCHAR (100)
   ,@ImageFolderPath NVARCHAR(1000)
   ,@Filename NVARCHAR(1000)
   DECLARE @ImageData VARBINARY (max);
   DECLARE @Path2OutFile NVARCHAR (2000);
   SELECT @ImageData = (
         SELECT convert (VARBINARY (max), PictureData, 1)
         FROM Pictures
         WHERE pictureName = @PicName
   SET @Path2OutFile = CONCAT (
         , @Filename
     EXEC sp_OACreate 'ADODB.Stream' ,@Obj OUTPUT;
     EXEC sp_OASetProperty @Obj ,'Type',1;
     EXEC sp_OAMethod @Obj,'Open';
     EXEC sp_OAMethod @Obj,'Write', NULL, @ImageData;
     EXEC sp_OAMethod @Obj,'SaveToFile', NULL, @Path2OutFile, 2;
     EXEC sp_OAMethod @Obj,'Close';
     EXEC sp_OADestroy @Obj;
  EXEC sp_OADestroy @Obj;

Example Use

You have a file called Dragon.jpg in the C:\MyPictures\Input folder.

SQL import image example

In order to import to SQL Server execute the following:

exec dbo.usp_ImportImage 'DRAGON','C:\MyPictures\Input','Dragon.jpg' 

The data is now inside the pictures table and looks like this, if we query the table.

picture name

In order to export the file, use the following:

exec dbo.usp_ExportImage 'DRAGON','C:\MyPictures\Output','Dragon.jpg' 

The file is now exported to C:\MyPictures\Output\Dragon.jpg.

Next Steps
  • You can create these simple procedures and table in your database and use them for handling image files (or any other binary files). 
  • Make sure you assign the needed privileges.
  • The procedures were tested on SQL Server 2014 - 12.0.2000.8 (Intel X86) Standard Edition

Last Updated: 2017-07-17

get scripts

next tip button

About the author
MSSQLTips author Eli Leiba Eli Leiba is a senior application DBA, a teacher and a senior database consultant with 19 years of RDBMS experience.

View all my tips

Post a comment or let the author know this tip helped.

All comments are reviewed, so stay on subject or we may delete your comment. Note: your email address is not published. Required fields are marked with an asterisk (*).

*Name    *Email    Email me updates 

Signup for our newsletter
 I agree by submitting my data to receive communications, account updates and/or special offers about SQL Server from MSSQLTips and/or its Sponsors. I have read the privacy statement and understand I may unsubscribe at any time.


Wednesday, October 16, 2019 - 11:07:55 AM - Eli Leiba Back To Top

Please enable the 'Ole Automation Procedures' option by using the following script:

USE master; 
EXEC sp_configure 'show advanced option', '1'; 
EXEC sp_configure 'Ole Automation Procedures', '1'; 

Wednesday, October 16, 2019 - 4:59:59 AM - Martin Back To Top

There's just one problem: on some servers you might get an error:

SQL Server blocked access to procedure 'sys.sp_OADestroy' of component 'Ole Automation Procedures' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'Ole Automation Procedures' by using sp_configure. For more information about enabling 'Ole Automation Procedures', search for 'Ole Automation Procedures' in SQL Server Books Online.

Wednesday, April 03, 2019 - 1:56:44 PM - Alex Back To Top

Thanks for posting this tutorial! I'm glad I finaly learned a simple way to extract images from SQL server today :)

Could you please explaine why there is a need to convert PictureData to VARBINARY (max inside select @ImageData? I thought when you create the Picture table the PictureData is already set to varbinary.


Thursday, January 10, 2019 - 12:11:35 PM - Robert Bardwell Back To Top

Yes yes yes!!! Worked like a charm and saved hours of time. 

As some asked below, yes it's possible to extract all the images from the table into a single folder...  I just moved the variables directly into the code instead of running it as a stored procedure, making the filename change dynamically based on the image description in my table... and then did a WHILE loop to pull them all out.

Wednesday, November 14, 2018 - 1:42:26 PM - Ali Back To Top


Thank you for your good article.

I want to import excel file which contain picture, do you have a idea how can I do that.

Many Thanks,


Tuesday, April 17, 2018 - 4:52:35 PM - Carlos Torres Back To Top

Hi Eli,

I did all those steps in a SQL Server 2008

I dont get any error message but when I checked the folder , its empty. Any idea why ?

Here is my code:



--Drop table [BLOBtest]



-- [Doc_Num] [numeric](18, 0) IDENTITY(1,1) NOT NULL,

-- [Extension] [varchar](50) NULL,

-- [FileName] [varchar](200) NULL,

-- [Doc_Content] [varbinary](max) NULL



--INSERT [dbo].[BLOBtest] ([Extension] ,[FileName] , [Doc_Content] )

--SELECT 'jpg', 'mmsync.jpg',[Doc_Data].*


--    (BULK '\\Testfolder\TEMP\images\mmsync.jpg', SINGLE_BLOB)  [Doc_Data]


--INSERT [dbo].[BLOBtest] ([Extension] ,[FileName] , [Doc_Content] )

--SELECT 'jpg', 'BC image 1.jpg',[Doc_Data].*


--    (BULK '\\Testfolder\TEMP\images\BC image 1.jpg', SINGLE_BLOB)  [Doc_Data]


--INSERT [dbo].[BLOBtest] ([Extension] ,[FileName] , [Doc_Content] )

--SELECT 'jpg', 'Russia2018.jpg',[Doc_Data].*


--    (BULK '\\Testfolder\TEMP\images\Russia2018.jpg', SINGLE_BLOB)  [Doc_Data]


Select * from [BLOBtest]




DECLARE @outPutPath varchar(50) = '\\Testfolder\TEMP\images\BLOB'

, @i bigint

, @init int

, @data varbinary(max) 

, @fPath varchar(max)  

, @folderPath  varchar(max) 


--Get Data into temp Table variable so that we can iterate over it 

DECLARE @Doctable TABLE (id int identity(1,1), [Doc_Num]  varchar(100) , [FileName]  varchar(100), [Doc_Content] varBinary(max) )


INSERT INTO @Doctable([Doc_Num] , [FileName],[Doc_Content])

Select [Doc_Num] , [FileName],[Doc_Content] FROM  [dbo].[BLOBtest]


--SELECT * FROM @table


SELECT @i = COUNT(1) FROM @Doctable


WHILE @i >= 1




@data = [Doc_Content],

@fPath = @outPutPath + '\'+ [FileName],

@folderPath = @outPutPath + '\'+ [Doc_Num]

FROM @Doctable WHERE id = @i


  -- EXEC master.master.dbo.xp_cmdshell @folderPath

  -- Create folder first

  -- EXEC master.dbo.xp_cmdshell @outPutPath

  -- EXEC  [dbo].[CreateFolder]  @folderPath


  Begin Try

  EXEC sp_OACreate 'ADODB.Stream', @init OUTPUT; -- An instace created

  EXEC sp_OASetProperty @init, 'Type', 1;  

  EXEC sp_OAMethod @init, 'Open'; -- Calling a method

  EXEC sp_OAMethod @init, 'Write', NULL, @data; -- Calling a method

  EXEC sp_OAMethod @init, 'SaveToFile', NULL, @fPath, 2; -- Calling a method

  EXEC sp_OAMethod @init, 'Close'; -- Calling a method

  EXEC sp_OADestroy @init; -- Closed the resources

  End Try


  Begin CATCH

  EXEC sp_OADestroy @init; -- Closed the resources



  print 'Document Generated at - '+  @fPath   


  --Reset the variables for next use

  SELECT @data = NULL  

  , @init = NULL

  , @fPath = NULL  

  , @folderPath = NULL

  SET @i -= 1




Thursday, March 15, 2018 - 10:15:44 AM - Kaare Back To Top


 Is it possible to extract multiple pictures at once with the same Exec?

Sunday, August 06, 2017 - 7:24:32 PM - Nosa Osayamwen Back To Top



Thanks for a very nice article. I tried a scenario whereby I want to update a picture for an employee with a new picture, I could not get it to work, can you help me out? Thanks.

Wednesday, July 19, 2017 - 7:46:55 AM - Eli Leiba Back To Top

 The error handling TRY & Catch block was added to the export procedure.


Wednesday, July 19, 2017 - 1:27:01 AM - Salman Sadiq Back To Top

Awesome tsql code to handle and store images files in db

a lil costly on memory if something strangled due to any error as said by scott coleman.

Overall worth teaching.

Thanks for sharing.

Monday, July 17, 2017 - 6:49:49 PM - jeff_yao Back To Top

My concern is that sp_OA* system stored procedures require sysadmin privileges as stated here - https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-oacreate-transact-sql.

Further, using sp_OA* system stored procedures is out-dated and a potential issue for a company that subject to 3rd party audits.

Monday, July 17, 2017 - 1:40:33 PM - Scott Eichman Back To Top

 Interesting solution for reading and writig files. MS-SQL has never been very good about natively interfacing with the OS. The way I solved the problem of reading and writing files was to create CLR C# functions. One to read a file into a VARBINARY(MAX) and the other to write a VARBINARY(MAX) to a file. Using C# makes the actions very efficient.

Thanks for the article!


Monday, July 17, 2017 - 11:01:42 AM - David Primus, DBA Back To Top

sp_OACreate method is notorious for memory leaks.  Best Practices is to run these from staging sql servers, not on production sql servers. SqlCLR  proovides "managed code" which largely replaces these older unmanaged coding techniques.


Monday, July 17, 2017 - 9:50:59 AM - Scott Coleman Back To Top

This is a good post for anyone who did not know T-SQL alone could be used to read and write files.  However I have a complaint.

The file writing subroutine is seriously flawed because it uses object automation with no error handling.  The possible errors that could occur include a nonexistent or malformed path, permission errors, disk full errors.  Any of these would interrupt the routine and skip the call to sp_OADestroy, leaving the stream object allocated in memory forever (or until the next reboot, whichever comes first).  I would not object so strenuously if you had included a note such as "Error handling removed for clarity", but to not even mention it is unacceptable.

I think moving the file IO to CLR routines is a better plan.  Using .Net managed code instead of COM objects should lead to a more stable SQL environment.

Some CLR file IO tips on this website:


Monday, July 17, 2017 - 2:14:30 AM - György Görög Back To Top

This is a nice post. It may be worth to mention that many image formats that are designed to go through the internet w/o further encoding, that is, contain only ASCII characters < 128, can be stored in text columns, not even nText. GIF and JPG come to mind. My apps store these images this way for decades now (I have to admit) and I never had any problems with that. An advantage is that you can read the first few characters that specify the format w/o getting the whole image, in case you don't store the format in a separate column.

But true, varbinary is really insensitive for format and compression etc. so it's more universal.   



Learn more about SQL Server tools