【问题标题】:C# SQL insert commandC# SQL 插入命令
【发布时间】:2012-01-03 08:50:30
【问题描述】:

谁能告诉我以下两种插入记录的方法可以带来更好的性能?

案例 1

SqlCommand cmd = new SqlCommand();

for (int i = 0; i < 10000; i++)
{
  cmd = new SqlCommand("insert into test(id, name) value('" + i + "', '" + i + "')");
  cmd.ExecuteNonQuery();
}

案例 2

string sql = null;

for (int i = 0; i < 10000; i++)
{
  sql += "insert into test(id, name) value('" + i + "', '" + i + "')";
}

SqlCommand cmd = new SqlCommand(sql, conn);
cmd.ExecuteNonQuery();

【问题讨论】:

  • 您进行过简单的时序测试吗?每个执行 10,000 次,看看哪个运行得更快。
  • 相同,但首选第一种情况。相同,因为您将使用连接池。
  • 首先:STOP 将您的 SQL 代码连接在一起!!这是邀请黑客使用 SQL 注入攻击您!请改用参数化查询
  • @DanAndrews:真的吗?!?!??您认为创建 10'000 个SqlCommand 实例并一个一个执行它们与创建单个实例并执行一次一样快???
  • 你是对的,它会更快。

标签: c# sql loops insert sqlcommand


【解决方案1】:

首先:停止将您的 SQL 代码连接在一起!!这是邀请各地的黑客用 SQL 注入攻击你!请改用参数化查询

我会使用这个解决方案:创建一个带有参数化查询的单个SqlCommand,然后执行:

string stmt = "INSERT INTO dbo.Test(id, name) VALUES(@ID, @Name)";

SqlCommand cmd = new SqlCommand(smt, _connection);
cmd.Parameters.Add("@ID", SqlDbType.Int);
cmd.Parameters.Add("@Name", SqlDbType.VarChar, 100);

for (int i = 0; i < 10000; i++)
{
    cmd.Parameters["@ID"].Value = i;
    cmd.Parameters["@Name"].Value = i.ToString();

    cmd.ExecuteNonQuery();
}

或使用SqlBulkCopy,尤其是当您要插入超过 10,000 行时。

【讨论】:

  • 虽然我通常同意将未经处理的参数直接传递给连接的 SQL 是不好的 - 在这段代码的上下文中,它实际上是无害的。没有需要关注的用户输入值 - 它看起来像一个快速的一次性操作。
  • 新的推荐方式是使用AddWithValue
  • @Si8:绝对不是!!! - 见 Dan Guzman 说:"AddWithValue is Evil" - 请阅读这篇文章并停止使用它!
  • 嗯,我记得在某处看到过,但现在找不到了。你是对的......谢谢。
  • 我会想象 VS 和 C# 是微软,他们不会推荐不准确的东西,但再次使用 SharePoint 绝对不是这种情况!即使 VS 给我警告,我也会坚持使用Add()
【解决方案2】:

第二种方法看起来比 #1 更快,因为您立即发送 INSERT 命令。首先,每个 ExecuteNonQuery 都需要往返 SQL 服务器。

但是您应该尝试批量插入命令:BULK INSERT (Transact-SQL),我想您将获得比您提供的任何一个选项更好的性能。

[]的

【讨论】:

  • 虽然这可能是个好主意,但它如何回答“选项 1 或选项 2 哪个更快?”的问题。您说过“改为执行选项 3”。
  • @KenWhite 我认为答案非常合适。它没有直接回答这个问题,因为 OP 正在使用低效的流程。我有一种预感,OP 并不是在寻找究竟哪种方式使用更少的 CPU 周期(因为如果这正是他们想知道的,他们可以很容易地测试自己)。相反,我相信 OP 正在尝试了解哪种方式更有效,并且 Fabio 提供了比任何 OP 都更好的解决方案。
  • 它没有。正如你所说,这是第三种选择。有时我们并没有得到我们想要的确切答案,但我们得到了让我们从不同的角度看待事物的东西。 []的
  • 当他们没有回答一个非常具体的问题时,我真的很讨厌看到被投票的答案。
  • 如果是第三种选择,可以将其作为脚注添加到实际回答所提问题的答案中,或者作为对原始问题的评论。这不是对所提问题的回答,也不应该这样发布。我本可以直接投反对票或将其标记为“不是答案”;我没有。我给了张贴者一个机会来扩展提供的答案或先将其删除。答案实际上应该这样做 - 回答提出的问题。然后可以提供有关替代方案的其他建议或信息。
【解决方案3】:

应该注意的是,这两种情况都不会起作用。

案例 #1 需要指定连接。

案例 #2 要求您以分号结束语句以运行多个命令,如下所示:

string sql = null;

for (int i = 0; i < 10000; i++)
{
  sql += "insert into test(id, name) value('" + i + "', '" + i + "');";
}

SqlCommand cmd = new SqlCommand(sql, conn);
cmd.ExecuteNonQuery();

最终,最好的方法是您自己在数千行上进行测试。我的猜测是,案例 #2 的性能会更好,因为它不仅需要设置一个 SqlCommand 对象,而且只需要访问数据库一次。

【讨论】:

    【解决方案4】:

    我认为第二个行不通。

    但是,SQL Server 2008 中有 inserting multiple rows in a single INSERT statement 的语法,我认为这将比您提出的两个选项更快:

    INSERT INTO test (id, name)
    VALUES
    ('1', 'foo'),
    ('2', 'bar'),
    ('3', 'baz')
     -- etc...
    

    但是,如果您真的想要高性能,请考虑使用 SqlBulkCopy 类。

    【讨论】:

      【解决方案5】:

      第二个可能更快,因为您最终只有一次往返。两者都同样糟糕,因为您不使用parameterized queries

      【讨论】:

      • @Kiley:除了煽动争论之外,我看不出你在这里发帖的意义。
      猜你喜欢
      • 1970-01-01
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      相关资源
      最近更新 更多