DCSIMG
SQL Server 2008 Table Valued Parameters - Guy Burstein's Blog

Guy Burstein's Blog

Developer Evangelist @ Microsoft

News

Guy Burstein The Bu

Disclaimer
Postings are provided 'As Is' with no warranties and confer no rights.

Guy Burstein LinkedIn Profile

TwitterCounter for @bursteg

Links

Articles

Blogs I Read

SQL Server 2008 Table Valued Parameters

SQL Server 2008 Table Valued Parameters

SQL Server 2008 Table Valued Parameters

A problem the data applications commonly have is when they have a grid of records that the clients creates (like a list of items in a store) and they want to insert in into the database in the most efficient way. The naive way is to insert the rows one by one, and another approach would be to create a stored procedure that takes a number of parameters with long strings or arrays of values and create a table from them. Another approach would be to use an Xml block parameter and parse it inside the procedure.

Assuming we have a Customers table:

create table Customers

(

    CustomerID    int not null primary key identity(1,1),

    Name          varchar(50) not null,

    City          varchar(50) null,

    Phone         varchar(10) null,

)

and a stored procedure that inserts customers rows:

create procedure CustomerInsert

    @Name        varchar(50),

    @City        varchar(50),

    @Phone       varchar(10)

as

    insert

    into Customers (Name, City, Phone)

    values (@Name, @City, @Phone)

go

We would go and call it for each customer row we want to insert:

using (SqlConnection conn = new SqlConnection("..."))

{

  SqlCommand cmd = conn.CreateCommand();

  cmd.CommandType = System.Data.CommandType.StoredProcedure;

  cmd.CommandText = "dbo.CustomerInsert";

  cmd.Parameters.AddWithValue("@Name", (string)row["Name"]);

  cmd.Parameters.AddWithValue("@City", (string)row["City"]);

  cmd.Parameters.AddWithValue("@Phone", (string)row["Phone"]);

 

  conn.Open();

  cmd.ExecuteNonQuery();

}

Nowdays, we can use SQL Server 2008 Table Valued Parameters and solve this problem in the most efficient way, and still use the same ADO.Net API you use in your application.

First, we should declare a new Table User Defined Type in the database:

create type CustomerTableType as table

(

    Name        varchar(50),

    City        varchar(50),

    Phone       varchar(10)

)

Then we can create a stored procedure that gets a parameter of that type, and inserts many rows in a single command.

create procedure CustomersInsertMany

(

    @CustomersTable CustomerTableType readonly

)

as

    insert

    into   Customers (Name, City, Phone)

    select Name, City, Phone

    from   @CustomersTable;

To execute this procedure using script, I declare a new instance of the Table Valued Parameter type, and insert rows into it. Then I execute the store procedure in order to insert all the rows all together.

declare @customers_temp CustomerTableType

insert into @customers_temp values ('Customer #4', 'Jerusalem', '2343245')

insert into @customers_temp values ('Customer #5', 'Tel Aviv', '0987345')

insert into @customers_temp values ('Customer #6', 'Haifa', '275466')

 

execute CustomersInsertMany @customers_temp

For ADO.Net, the code really looks similar to the above. First I create a data table, and fill it with data:

// Create a data table, and provide its structure

DataTable customerTable = new DataTable();

customerTable.Columns.Add("Name", typeof(string));

customerTable.Columns.Add("City", typeof(string));

customerTable.Columns.Add("Phone", typeof(string));

 

// Fill with rows

customerTable.Rows.Add("Customer #1", "Berlin", "123");

customerTable.Rows.Add("Customer #2", "Paris", "567");

customerTable.Rows.Add("Customer #3", "London", "789");

Then, I call the above stored procedure and pass the data table as a parameter.

using (SqlConnection conn = new SqlConnection("..."))

{

  SqlCommand cmd = conn.CreateCommand();

  cmd.CommandType = System.Data.CommandType.StoredProcedure;

  cmd.CommandText = "dbo.CustomersInsertMany";

  SqlParameter param = cmd.Parameters.AddWithValue("@CustomersTable", customerTable);

 

  conn.Open();

  cmd.ExecuteNonQuery();

}

Enjoy!

Comments

Nir Kovalio said:

פיצ'ר מעניין, היום אני עושה את זה עם BulkInsert.

# December 2, 2007 10:42 PM

גיא בורשטיין said:

Watch Mike Taulty in his new video about SQL Server 2008 table valued parameters:

mtaulty.com/.../9991.aspx

# December 3, 2007 4:00 PM

ламинат said:

9yI'll thingk about it.3q I compleatly agree with last post.  hjb

<a href="http://skuper.ru">ламинированный паркет</a> 8a

# August 24, 2008 7:59 AM

ламинат said:

9aThank's for greate post.9w I compleatly agree with last post.  mtf

<a href="http://skuper.ru">паркет</a> 6x

# August 24, 2008 12:21 PM

ламинат said:

6dGood idea.4k I compleatly disagree with last post .  lyo

<a href="http://skuper.ru">купить ламинат</a> 0c

# August 24, 2008 9:03 PM

ламинат said:

4zGood idea.3q I compleatly agree with last post.  hff

<a href="http://skuper.ru">ламинат</a> 0o

# August 24, 2008 11:24 PM

сайдинг said:

5uI'll thingk about it.5l I compleatly agree with last post.

<a href="all-siding.ru/index.php канадский</a> 7k

<a href="all-siding.ru/index.php сайдинг</a> 7c

# August 25, 2008 10:49 AM

Jose Garci said:

HEllo,

Could I get the DataSet.Update method to use table-valued parameters automatically ?

How?

# November 29, 2008 2:16 PM

EnterpriseLibrary.Data and inserting/updating more than 1 row at a time. | keyongtech said:

Pingback from  EnterpriseLibrary.Data and inserting/updating more than 1 row at a time. | keyongtech

# March 6, 2009 3:07 AM

Martin Bell UK SQL Server MVP said:

One advantage of the Table-valued parameter (TVP) is that you can build up the data for the TVP within a client application. Here is show how easy it is to pass a Datatable as a TVP in a simple .NET application.

# May 11, 2009 5:48 PM

Balaji said:

Excellent article. Very neatly explained.. It helped a lot for me... Thnx a lot buddy...

# May 14, 2010 2:23 PM

420sel Parts Wiper Blade Fuel Filter, 420sel Part Buy 1990 Mercedes Benz Hid Xenon said:

Pingback from  420sel Parts Wiper Blade Fuel Filter, 420sel Part Buy 1990 Mercedes Benz Hid Xenon

# May 21, 2010 3:02 AM

R21 Tahoe Torrent, Dvd Tahoe Hector Herrera said:

Pingback from  R21 Tahoe Torrent, Dvd Tahoe Hector Herrera

# May 22, 2010 4:35 PM

Mercedes Benz S600 S65 Sl63 Amg, Used Mercedes S600 Engines - 415.animejin.com said:

Pingback from  Mercedes Benz S600 S65 Sl63 Amg, Used Mercedes S600 Engines - 415.animejin.com

# May 23, 2010 11:54 AM

Pontiac Aztek Part Fog Light Mounting Bracket, Aztek Toyota Cars - 153.cmanager.org said:

Pingback from  Pontiac Aztek Part Fog Light Mounting Bracket, Aztek Toyota Cars - 153.cmanager.org

# May 25, 2010 2:50 AM

2000 - 1996 @ Denali Forum Gmc Yukon Xl, 1993 Sierra Denali 2007 Gmc Yukon - 375.dlmreza.net said:

Pingback from  2000 - 1996 @ Denali Forum Gmc Yukon Xl, 1993 Sierra Denali 2007 Gmc Yukon - 375.dlmreza.net

# May 27, 2010 1:28 PM

1999 - 2002 @ W100 Restoration Pickup Pictures, Benq W100 Review Colour Wheel - 0.tgrconversions.com said:

Pingback from  1999 - 2002 @ W100 Restoration Pickup Pictures, Benq W100 Review Colour Wheel - 0.tgrconversions.com

# May 27, 2010 4:06 PM

A Generic Base Class for LINQ-to-Entities Data Access in a Multi-Tier Application « Mel's space said:

Pingback from  A Generic Base Class for LINQ-to-Entities Data Access in a Multi-Tier Application &laquo; Mel&#039;s space

# November 22, 2010 12:46 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: