Introduction
A new type appeared in SQL server 2008. This type is Table.
You can now pass a table as parameter to a store procedure.
As sample we are going to send the selected values (multiple selection) of a listview to a store procedure in order to insert the data in a parent table and a child table.
Creating a new table user type
First of all we have to create a new table type
CREATE TYPE [dbo].[Tble_KeywordsID] AS TABLE( [ID_Keywords] [int] NOT NULL )

As you can see this type creation follow the same principle than a regular table.
Once created, you can visualize this table in databasename\programmability\types\User-Defined Table Types
It really looks like a table against witch you can define keys, constraints and indexes.
That means, you are not only passing data like in an array, but in a real table than can be optimized and indexed if necessary.
Below, I wrote a sample (asp.net / vb) where you can understand how to use pragmatically in a project this functionnality.
Table creation
CREATE TABLE [dbo].[Tble_Issues_Keywords]( [Id_Issues_Keywords] [int] IDENTITY(1,1) NOT NULL, [Id_Issue] [int] NULL, [Id_Keyword] [int] NULL, CONSTRAINT [PK_Tble_Issues_Keywords] PRIMARY KEY CLUSTERED ( [Id_Issues_Keywords] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO ALTER TABLE [dbo].[Tble_Issues_Keywords] WITH CHECK ADD CONSTRAINT [FK_Tble_Issues_Keywords_Tble_Issues] FOREIGN KEY([Id_Issue]) REFERENCES [dbo].[Tble_Issues] ([Id_Issue]) GO ALTER TABLE [dbo].[Tble_Issues_Keywords] CHECK CONSTRAINT [FK_Tble_Issues_Keywords_Tble_Issues] GO CREATE TABLE [dbo].[Tble_Issues]( [Id_Issue] [int] IDENTITY(1,1) NOT NULL, [Id_User] [int] NULL, [Id_Folder] [int] NULL, [Issue_Content] [char](50) NULL, [Issue_Description] [varchar](max) NULL, [Issue_Solution] [varchar](max) NULL, [Creation_Date] [datetime] NULL, [Update_Date] [datetime] NULL, CONSTRAINT [PK_Tble_Sujets] PRIMARY KEY CLUSTERED ( [Id_Issue] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
Stored procedure creation
CREATE PROCEDURE [dbo].[sp_Insert_Issues_Keywords_Folders] @Id_User INT ,@Id_Folder INT ,@Issue_Content CHAR(50) ,@Issue_Description VARCHAR(MAX) ,@Issue_Solution VARCHAR(MAX) ,@Tble_Id_Folders AS Tble_KeywordsID READONLY AS BEGIN TRANSACTION DECLARE @Id_Issue INT INSERT INTO dbo.Tble_Issues ( Id_User ,Id_Folder ,Issue_Content ,Issue_Description ,Issue_Solution ,Creation_Date ) VALUES ( @Id_User ,@Id_Folder ,@Issue_Content ,@Issue_Description ,@Issue_Solution ,GETDATE() ) SELECT @Id_Issue = @@IDENTITY INSERT INTO dbo.Tble_Issues_Keywords ( Id_Issue ,Id_Keyword ) SELECT @Id_Issue ,ID_Keywords FROM @Tble_Id_Folders COMMIT TRANSACTION
Code sample (VB.net)
The following code is based on a form that includes :
- A list named lstKeywords
- A stored procedure named sp_Search_Issues
- A connection named ConnectionInfo and stored in a separate XML file (using SSPI specification)
'-------------------------------------
' Variables declaration
'-------------------------------------
Imports System.Data.SqlClient
Public myConnection As SqlConnection = New SqlConnection(System.Configuration.ConfigurationSettings.AppSettings("ConnectionInfo"))
Private _dataTable As DataTable
Dim dt_KeywordsID As DataTable = New DataTable("Tble_KeywordsID")
Dim dtc_KeywordsID As DataColumn
Dim row As DataRow
Dim objCommand As SqlCommand
Dim objParam As SqlParameter
'-------------------------------------
' Create a connection to SQL Server
'-------------------------------------
objCommand = New SqlCommand("sp_Search_Issues", myConnection)
objCommand.CommandType = CommandType.StoredProcedure
objCommand.Connection.Open()
'-------------------------------------
' Create parameters for sp
'-------------------------------------
objParam = objCommand.Parameters.Add("@Id_Folder", SqlDbType.Int)
objParam.Value = CInt(lstFolders.SelectedValue)
objParam = objCommand.Parameters.Add("@Tble_Id_Folders", SqlDbType.Structured)
'-------------------------------------
' Prepare table as parameter
'-------------------------------------
dtc_KeywordsID = New DataColumn()
dtc_KeywordsID.DataType = Type.GetType("System.Int32")
dtc_KeywordsID.ColumnName = "ID_Keywords"
dt_KeywordsID.Columns.Add(dtc_KeywordsID)
'-------------------------------------
' Get the multiple selected values
'-------------------------------------
Dim intLoop As Integer
Dim valSelect As Integer
Dim colSelectedValues As New Collection
For intLoop = 0 To lstKeywords.Items.Count - 1
If lstKeywords.Items(intLoop).Selected Then
valSelect = lstKeywords.Items(intLoop).Value
row = dt_KeywordsID.NewRow()
row("ID_Keywords") = valSelect
dt_KeywordsID.Rows.Add(row)
End If
Next
'-------------------------------------
' Value affectation
'-------------------------------------
objParam.Value = dt_KeywordsID
'-------------------------------------
' Define a datareader and store the
' resultset of the sp's execution
' within this datareader
'-------------------------------------
Dim MyDataReader As SqlDataReader
MyDataReader = objCommand.ExecuteReader()
'-------------------------------------
' Define data value field and a
' data text field , source
' and bind the datareader to the list
' resultset of the sp's execution
' within this datareader
' Display the results in a listview
'-------------------------------------
lstViewIssuesResults.DataValueField = "Id_Issue"
lstViewIssuesResults.DataTextField = "Issue_Content"
lstViewIssuesResults.DataSource = MyDataReader
lstViewIssuesResults.DataBind()
'-------------------------------------
' Close the connexion object
'-------------------------------------
objCommand.Connection.Close()