我无法想办法在C#或SQL查询中执行批量SQL插入命令。
我通常会得到一个零件编号清单......有时候会有100多个零件
LTM-120
LTM-130
LTM-140
LTM-120
LTM-130
LTM-140
并且,我使用一个按钮将其插入C#中,因为......
Textbox20
是PartNumber,Textbox15
是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();
有没有办法对一堆零件号进行批量查询?或者有没有人对如何做这样的事情有任何想法?
答案 0 :(得分:1)
您可以使用SqlBulkCopy
对数据库进行批量插入。
// 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);
}
}
请参阅:MSDN
答案 1 :(得分:0)
或者你可以使用更安全的参数
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();
您还可以使用交易Executing query with parameters
答案 2 :(得分:0)
您可以读入数组并循环插入一行一行。我确信有比这更好的解决方案,但它会起作用。
伪代码 -
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()
}
基本上将数据放入和数组,循环遍历数组,拉出每个数据值并插入到数据库中。如果您有错误的数据,这可能会导致问题。您可能希望对SQL注入和参数进行一些研究,以实现一些方法以确保DB不会被破坏。
编辑:
虽然每次关闭连接更安全,但这种效果会有多快?我假设每次打开和关闭连接都比循环前打开慢,并在数据处理完成后关闭。
编辑2:
如上所述,但不是从静态文件填充,而是通过实现此处显示的浏览/打开文件功能从用户选择的文件中填充数组
http://msdn.microsoft.com/en-us/library/cc221415(v=vs.95).aspx
然后,除了要插入的新数据值之外,每个值的INSERT
语句都将保持不变。
答案 3 :(得分:0)
有许多不同的技术可以同时执行多个INSERT。其他答案已经讨论了这些(SqlBulkCopy,BULK INSERT等)
您还可以构建一次执行多个INSERT的SQL语句。例如,使用INSERT VALUES
,将多个VALUES子句串在一起:
INSERT INTO [Products].[Features] ([ProductID], [Title], [ViewOrder])
VALUES (1, 'Title 1', NULL),
(2, 'Title 2', NULL),
-- etc.
或者使用INSERT和UNION:
INSERT INTO [Products].[Features] ([ProductID], [Title], [ViewOrder])
SELECT 1, 'Title 1', NULL
UNION ALL SELECT 2, 'Title 2', NULL
UNION ALL -- etc.
但是,您确实需要小心参数。正如其他人所指出的那样,您当前的代码容易受到SQL注入攻击。
答案 4 :(得分:0)
批量复制肯定是一种方法。
但是,由于您的数据集相对较小(100项),因此您可以考虑使用SQL Server对XML的支持。给出这样一个表:
create table dbo.item
(
id int not null primary key clustered ,
name varchar(100) not null unique nonclustered ,
)
您可以编写如下存储过程:
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
可以像这样调用(在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>
'
或者,从C#,像这样:
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() ;
}
然后它是一个获取你的部件号列表并将其序列化为合适的XML(如果它还没有)并在存储过程中构建正确的XQuery / XPath以提取必要的位。
在现实世界中,由于XML处理可能既昂贵又痛苦,我发现最简单的方法是先让存储过程首先使用OpenXml()将XML加载到临时表中,以便处理XML前面的方式。完成后,存储过程的其余部分可以是直接SQL。它也简化了调试和维护。