Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SQL插入一行还是多行数据?_C#_Sql_Sql Server_Sql Server 2005_Tsql - Fatal编程技术网

C# SQL插入一行还是多行数据?

C# SQL插入一行还是多行数据?,c#,sql,sql-server,sql-server-2005,tsql,C#,Sql,Sql Server,Sql Server 2005,Tsql,我正在开发一个控制台应用程序,将数据插入MS SQL Server 2005数据库。我有一个要插入的对象列表。这里我使用Employee类作为示例: List<Employee> employees; 或者我可以像这样构建一个balk insert查询: foreach (Employee item in employees) { string sql = @"INSERT INTO Mytable (id, name, salary) values ('@id',

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

List<Employee> employees;
或者我可以像这样构建一个balk insert查询:

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();
}
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();
我想后一种情况是立即插入数据行。然而,如果我有 几ks的数据,SQL查询字符串是否有限制

就性能而言,我不确定一次多行插入是否优于一次一行数据插入

有什么更好的建议吗?

看看, 我已经回答了关于表值参数的问题。

通常比自己插入更快


如果您仍然希望使用建议的方法之一执行此操作,则应该这样做,以便可以轻松更改发送到服务器的查询的大小。这样,您可以在以后的生产环境中优化速度。根据查询大小,查询时间可能会有很多变化。

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

事实上,按照您编写它的方式,您的第一个选项会更快

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

  • 按照您的设置方式,当您最终发送一个大型查询时,SQL Server可能需要对其进行评估,这肯定需要一些时间来确定它应该做什么。我应该说,这取决于需要插入的数量。如果n很小,你可能会没事,但随着它的增长,你的问题只会变得更糟

  • 由于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;
    

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

    CREATE TYPE MyUdt AS TABLE (Id int, Name nvarchar(50), salary int)
    
    然后,您可以在存储过程中使用此UDT,并使用C#-代码批插入。 SP:

    C#(假设需要插入的记录已经包含在数据集ds的表“MyTable”中):

    这就是解决方案


    最后,我想阻止您使用类似您的代码(生成字符串,然后执行此字符串),因为这种执行方式可能用于SQL注入。

    调用SP而不是惰性SQL如何?SP将采用类似的参数,但在SP中,每个调用都有提交。如果任何SP调用失败,事务是否会回滚?@Kevin,为什么CommitTransaction不会在Intellisense中显示?事实上,我不知道。我得找出原因@Spike@Kevin不用担心:)这只是一个想法。
    CREATE PROCEDURE uspInsert
     (@MyTvp AS MyTable READONLY)
    AS
         INSERT INTO [MyTable]
          SELECT * FROM @MyTvp
    
    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();
    }