Reputation: 35
I am having trouble thinking of a way to do bulk SQL insert commands in C# or even a SQL query.
I usually get a part number list as so... sometimes its 100+ parts
LTM-120
LTM-130
LTM-140
LTM-120
LTM-130
LTM-140
And, I use a button to insert it in C# as so...
Textbox20
is the PartNumber and Textbox15
is the PartNumber ID
SqlConnection sqlCon3 = new SqlConnection("REMOVED");
SqlCommand sqlCmd3 = new SqlCommand();
sqlCmd3.CommandText = "INSERT INTO [Products].[Features] " +
"([ProductID] ,[Title] ,[ViewOrder]) VALUES ('" +
textBox15.Text + "', '" + textBox20.Text + "', NULL) ";
sqlCmd3.Connection = sqlCon3;
sqlCon3.Open();
sqlCmd3.ExecuteNonQuery();
sqlCon3.Close();
Is there any way to do a bulk query for a bunch of part numbers? Or does anyone have any ideas on how to do something like this?
Upvotes: 0
Views: 403
Reputation: 74267
Bulk Copy is certainly a way to go.
However, since your data set is relative small (100 items), you might consider using SQL Server's support for XML. Given a table like this:
create table dbo.item
(
id int not null primary key clustered ,
name varchar(100) not null unique nonclustered ,
)
You can write a stored procedure like this:
create procedure dbo.insert_items
@item_list xml
as
insert dbo.item
(
id ,
name
)
select id = X.value( './id[1]' , 'int' ) ,
name = ltrim(rtrim( X.value( './name[1]' , 'varchar(100)' ) ))
from @item_list.nodes('/items/item') as itemList(X)
return @@rowcount
go
which can be invoked like this (in SQL Server Management Studio):
exec insert_items '
<items>
<item><id> 1 </id><name> alpha </name></item>
<item><id> 2 </id><name> bravo </name></item>
<item><id> 3 </id><name> charlie </name></item>
<item><id> 4 </id><name> delta </name></item>
</items>
'
Or, from C#, like this:
string connect_string = "Server=localhost;Database=sandbox;Trusted_Connection=True;" ;
string myXmlString = @"
<items>
<item><id> 1 </id><name> alpha </name></item>
<item><id> 2 </id><name> bravo </name></item>
<item><id> 3 </id><name> charlie </name></item>
<item><id> 4 </id><name> delta </name></item>
</items>
" ;
using ( SqlConnection conn = new SqlConnection(connect_string) )
using ( SqlCommand cmd = conn.CreateCommand() )
{
cmd.CommandText = "dbo.insert_items" ;
cmd.CommandType = CommandType.StoredProcedure ;
cmd.Parameters.AddWithValue( "@item_list" , myXmlString ) ;
conn.Open() ;
cmd.ExecuteNonQuery() ;
conn.Close() ;
}
Then it's a taking your part number list and serializing it into suitable XML (if it's not already) and building the correct XQuery/XPath in your stored procedure to pull out the necessary bits.
In the real world, since XML processing can be...expensive and painful, I find it easiest to have the stored procedure first load the XML into a temporary table using OpenXml() first, just to get dealing with the XML out of the way up front. That done, the remainder of the stored procedure can be straight SQL. It simplifies debugging and maintenance, too.
Upvotes: 0
Reputation: 942
You could read into an array and loop through inserting one line at a time. I'm sure there are better solutions than this, but it will work.
Pseudocode-
Fill array from file
for(count int = 0; count < arr.length; count++)
{
sqlcon.open()
sqlcmd = New select statment with arr[count] values
sqlcmd.execute
sqlcon.close()
}
Essentially get your data into and array, loop through the array, pull each data value and insert into your DB. This can cause issues if you have bad data. You may want to do some research on SQL Injection and Parameters to implement some methods to ensure you DB doesn't get corrupted.
EDIT:
While safer with a close connection each time how much will this effect speed? I would assume opening and closing the connection every time would be slower than open before the loop and close after data processing is done.
EDIT 2:
Do as stated above, but instead of filling from a static file fill the array from the user selected file by implementing a browse/open file capability seen here
http://msdn.microsoft.com/en-us/library/cc221415(v=vs.95).aspx
Then your INSERT
statement will remain constant for each value except for the new data value being inserted.
Upvotes: 0
Reputation: 17020
There are many different techniques for doing multiple INSERTs at once. Other answers have discussed these (SqlBulkCopy, BULK INSERT, etc.)
You can also build a SQL statement that does multiple INSERTs at once. For example, using INSERT VALUES
, string multiple VALUES clauses together:
INSERT INTO [Products].[Features] ([ProductID], [Title], [ViewOrder])
VALUES (1, 'Title 1', NULL),
(2, 'Title 2', NULL),
-- etc.
Or use INSERT with a UNION:
INSERT INTO [Products].[Features] ([ProductID], [Title], [ViewOrder])
SELECT 1, 'Title 1', NULL
UNION ALL SELECT 2, 'Title 2', NULL
UNION ALL -- etc.
You really need to be careful with your parameters, however. As others have pointed out, your current code is vulnerable to SQL injection attacks.
Upvotes: 0
Reputation: 646
or you can use parameters its safer
SqlConnection sqlCon3 = new SqlConnection("REMOVED");
SqlCommand sqlCmd3 = new SqlCommand();
sqlCmd3.CommandText = "INSERT INTO [Products].[Features] ([ProductID] ,[Title] ,[ViewOrder]) VALUES (@myID, @myTitle, NULL) ";
sqlCmd3.Connection = sqlCon3;
sqlCon3.Open();
for (int i = 0; i < 10; i++)
{
sqlCmd3.Parameters.Add("myID", SqlDbType.Int).Value = myobjID[i];
sqlCmd3.Parameters.Add("myTitle", SqlDbType.Text).Value = myobjTitle[i];
sqlCmd3.ExecuteNonQuery();
sqlCmd3.Parameters.Clear();
}
sqlCon3.Close();
you can also use transactions Executing query with parameters
Upvotes: 0
Reputation: 6111
You can use SqlBulkCopy
to do mass inserts to the DB.
// Create a table with some rows.
DataTable newProducts = MakeTable();
// Create the SqlBulkCopy object.
// Note that the column positions in the source DataTable
// match the column positions in the destination table so
// there is no need to map columns.
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.DestinationTableName =
"dbo.BulkCopyDemoMatchingColumns";
try
{
// Write from the source to the destination.
bulkCopy.WriteToServer(newProducts);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
See: MSDN
Upvotes: 1