tags:

views:

812

answers:

10

How do I/what’s the best way to bulk database inserts?

From a c# perspective I am iterating over a collection and calling an insert stored procedure for each item in the collection.

How do I send all the data in one database call?

E.g. say I have a person list (List) containing 10 items, I am currently calling the InsertPerson store proc 10 times. I would like to reduce this to 1 call.

/I am using MS SQL Server 2005.

Thanks a lot.

+1  A: 

Dump your data to a pipe delimited (or something else if your data has pipes in it) text file and use Bulk Insert.

Jason Punyon
The method needs to be programatic and fast - no disk i/o. Thank you.
You could do it using MemoryStream to avoid File I/O, but you're probably just doing a boilerplate implementation SQLBulkCopy. See my comment to @Mark Gavell's answer.
Michael Meadows
+2  A: 

You can build a BLOB (image) and send it as a parameter to a stored procedure. Inside the stored procedure, you can fetch all the items using substring().

daanish.rumani
+7  A: 

The .NET SqlBulkCopy class works quite well.

MichaelGG
+1  A: 

You could update with an Xml document, Sql 2005 works very well with them. One node per row, but just one parameter for Xml.

dove
+10  A: 

Well, 10 items isn't what I call bulk, but for larger sets, SqlBulkCopy is your friend. All you need to do is feed it either a DataTable or an IDataReader (my preferred option, 'cos I like streaming APIs). I did something similar here (you can ignore the xml side - just subclass the SimpleDataReader).

Marc Gravell
Marc: do you know what's under the hood of SqlBulkCopy?
Jason Punyon
+1 for "streaming APIS". @Jason, my guess is SqlBulkCopy wraps the BULK insert statement: http://technet.microsoft.com/en-us/library/ms187042.aspx
Michael Meadows
Sorry - was AFK - it is essentially the same API as "bcp" etc use - but directly via a TDS stream (it doesn't wrap an exe, or similar).
Marc Gravell
+1  A: 

Here's a good example of SqlBulkCopy in action:

http://blogs.msdn.com/nikhilsi/archive/2008/06/11/bulk-insert-into-sql-from-c-app.aspx

John Rasch
+1  A: 

Create a XML document that contains all the items to be inserted. Then inside of a stored procedure, use the TSQL xml support (OPENXML) to read all the data from the XML document and insert it into your tables with hopefully one insert statement for each table.

However if you are only inserting data into a single table and don’t need any database side logic, why not use SqlBulkCopy?

Ian Ringrose
You don't need to use OPENXML with SQL 2005, just use the built in XML data type.
Adam Hughes
@Adam, OPENXML is still usefull if you are just using the XML as a way to transport rows. However the SQL 2005 XML data types are very useful if you wish to store the XML in te database.
Ian Ringrose
+1  A: 

Definitely check this question. The topvoted answer (no, it's not mine:p) presents a very elegant solution to this exact problem.

Brann
He's using Sql Server 2005
Paul Suart
+2  A: 

I construct the list as an xml string and pass it to the stored proc. In SQL 2005, it has enhanced xml functionalities to parse the xml and do a bulk insert.

check this post: Passing lists to SQL Server 2005 with XML Parameters

Gulzar
+3  A: 

CsharperGuyInLondon, here's a simple example of SqlBulkCopy code:

using System.Data.SqlClient;

DataTable table = new DataTable("States");
// construct DataTable
table.Columns.Add(new DataColumn("id_state", typeof(int))); 
table.Columns.Add(new DataColumn("state_name", typeof(string)));

// note: if "id_state" is defined as an identity column in your DB,
// row values for that column will be ignored during the bulk copy
table.Rows.Add("1", "Atlanta");
table.Rows.Add("2", "Chicago");
table.Rows.Add("3", "Springfield");

using(SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString))
{
  bulkCopy.BulkCopyTimeout = 600; // in seconds
  bulkCopy.DestinationTableName = "state";
  bulkCopy.WriteToServer(table);
}
JohnB