SQL插入一行或多行数据?

时间:2009-06-21 15:11:12

标签: c# sql sql-server sql-server-2005 tsql

我正在使用控制台应用程序将数据插入MS SQL Server 2005数据库。我有一个要插入的对象列表。这里我以Employee类为例:

List<Employee> employees;

我能做的就是像这样插入一个物体:

foreach (Employee item in employees)
{
  string sql = @"INSERT INTO Mytable (id, name, salary) 
    values ('@id', '@name', '@salary')";
  // replace @par with values
  cmd.CommandText = sql; // cmd is IDbCommand
  cmd.ExecuteNonQuery();
}

或者我可以像这样构建一个balk插入查询:

string sql = @"INSERT INTO MyTable (id, name, salary) ";
int count = employees.Count;
int index = 0;
foreach (Employee item in employees)
{
   sql  = sql + string.format(
     "SELECT {0}, '{1}', {2} ",
     item.ID, item.Name, item.Salary);
   if ( index != (count-1) )
      sql = sql + " UNION ALL ";
   index++
 }
 cmd.CommandType = sql;
 cmd.ExecuteNonQuery();

我想后一种情况是一次性插入数据行。但是,如果我有 几个k的数据,SQL查询字符串是否有任何限制?

我不确定在性能方面,一行插入多行是否优于一行插入一行数据?

有什么建议以更好的方式做到这一点吗?

5 个答案:

答案 0 :(得分:14)

实际上,你写它的方式,你的第一个选择会更快。

  1. 您的第二个示例中存在问题。你正在做sql = + sql +等。这将导致为循环的每次迭代创建一个新的字符串对象。 (查看StringBuilder类)。从技术上讲,您将在第一个实例中创建一个新的字符串对象,但区别在于它不必复制上一个字符串选项中的所有信息。

  2. 你设置它的方式,当你最终发送它时,SQL Server将不得不潜在地评估一个大量的查询,这肯定需要一些时间来弄清楚它应该做什么。我应该说,这取决于你需要做多大的插入。如果n很小,你可能会好起来,但随着它的增长你的问题只会变得更糟。

  3. 由于SQL Server处理批处理事务的方式,批量插入比单个插入更快。如果要从C#插入数据,则应采用第一种方法并将每500次插入包装说明并提交,然后执行下一次500,依此类推。这样做的另一个好处是,如果批次失败,您可以捕获这些并找出出错的地方并重新插入。还有其他方法可以做到,但这绝对是对所提供的两个例子的改进。

    var iCounter = 0;
    foreach (Employee item in employees)
    {
    
       if (iCounter == 0)
      {
        cmd.BeginTransaction;
      }
      string sql = @"INSERT INTO Mytable (id, name, salary) 
        values ('@id', '@name', '@salary')";
      // replace @par with values
      cmd.CommandText = sql; // cmd is IDbCommand
      cmd.ExecuteNonQuery();
      iCounter ++;
      if(iCounter >= 500)
      {
         cmd.CommitTransaction;
         iCounter = 0;
      }
    }
    
    if(iCounter > 0)
       cmd.CommitTransaction;
    

答案 1 :(得分:3)

在MS SQL Server 2008中,您可以创建包含表格的.Net table-UDT

CREATE TYPE MyUdt AS TABLE (Id int, Name nvarchar(50), salary int)

然后,您可以在存储过程中使用此UDT,并将с#-code用于批量插入。 SP:

CREATE PROCEDURE uspInsert
 (@MyTvp AS MyTable READONLY)
AS
     INSERT INTO [MyTable]
      SELECT * FROM @MyTvp

C#(想象一下你需要插入的记录已包含在DataSet ds的表“MyTable”中):

using(conn)
{
    SqlCommand cmd = new SqlCommand("uspInsert", conn);
    cmd.CommandType = CommandType.StoredProcedure;

    SqlParameter myParam = cmd.Parameters.AddWithValue
     ("@MyTvp", ds.Tables["MyTable"]);

    myParam.SqlDbType = SqlDbType.Structured;
    myParam.TypeName = "dbo.MyUdt";

    // Execute the stored procedure
    cmd.ExecuteNonQuery();
}

所以,这就是解决方案。

最后,我想阻止你使用像你这样的代码(构建字符串然后执行这个字符串),因为这种执行方式可以用于SQL注入。

答案 2 :(得分:0)

看看this thread, 我在那里回答了有关表值的参数。

答案 3 :(得分:0)

Bulk-copy通常比自行插入更快。

如果您仍希望以建议的方式执行此操作,则应该可以轻松更改发送到服务器的查询的大小。这样,您可以在以后优化生产环境中的速度。查询时间可能很长,具体取决于查询大小。

答案 4 :(得分:0)

SQL Server查询的批处理大小列为65,536 *网络包大小。网络数据包大小默认为4kbs,但可以更改。查看SQL 2008的Maximum capacity articl e以获取范围。 SQL 2005似乎也有相同的限制。

相关问题