更快的插入方式C#& amp; SQL

时间:2013-12-20 19:12:02

标签: c# sql sql-server

我无法想办法在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();

有没有办法对一堆零件号进行批量查询?或者有没有人对如何做这样的事情有任何想法?

5 个答案:

答案 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。它也简化了调试和维护。