【问题标题】:Sql update command with optional parameters?带有可选参数的sql更新命令?
【发布时间】:2012-01-24 23:19:32
【问题描述】:

我将大约 500 000 个对象插入到数据库中,其中许多对象是相同的(在数据库中具有相同的主键表示),但其他字段可能不同,因此我使用方法“更新 - 如果没有受影响的行 - 插入” .问题是有时一个对象的某些字段设置为 null (从文件中无法读取)并且已经在数据库中设置了一些值,因此我将其更新为 null = 擦除它。)如何实现场景,您将只更新字段不为空?

这是我现在如何做的一个简单示例:

private const string UpdateKun = "UPDATE pde.Kun SET Jmeno=@Jmeno WHERE Licence=@Licence";
private const string InsertKun = "INSERT INTO pde.Kun ([Licence], [Jmeno], [VykonnostniStupen]) VALUES (@Licence, @Jmeno, @VykonnostniStupen)";

var cmd = new SqlCommand(UpdateKun, conn, tran);
cmd.Parameters.AddWithValue("@Licence", kun.Licence);
cmd.Parameters.AddWithValue("@Jmeno", kun.Jmeno);
RepairNulls(cmd.Parameters);
if (cmd.ExecuteNonQuery() > 0) return;

cmd = new SqlCommand(InsertKun, conn, tran);
cmd.Parameters.AddWithValue("@Licence", kun.Licence);
cmd.Parameters.AddWithValue("@Jmeno", kun.Jmeno);
cmd.Parameters.AddWithValue("@VykonnostniStupen", 0);
RepairNulls(cmd.Parameters);
cmd.ExecuteNonQuery();


private void RepairNulls(SqlParameterCollection col)
    {
        foreach (SqlParameter param in col.Cast<SqlParameter>().Where(param =>  param.Value == null))
        {
            param.Value = DBNull.Value;
        }
    }

【问题讨论】:

  • 某些 SQL 产品具有您用一条语句描述的功能:INSERT ... IF DUPLICATE UPDATE ...
  • @ypercube 因为它是 SqlCommand 它的 SQL Server。那么只要 2005 年或更大,它就会被 MERGE
  • 是的,我不是很喜欢 sql,但我认为它应该具有该功能 :) 我使用 Sql server 2008,express edition,我将查找 MERGE 语法,谢谢

标签: c# sql


【解决方案1】:

将更新更改为:

UPDATE pde.Kun 
SET Jmeno=@Jmeno 
WHERE Licence=@Licence
  AND @Jmeno IS NOT NULL

如果您有多个列要更新:

UPDATE pde.Kun 
SET Jmeno = COALESCE(@Jmeno, Jmeno)
  , ColumnB = COALESCE(@ColumnB, ColumnB) 
WHERE Licence=@Licence

【讨论】:

  • 好主意,似乎是解决方案,即使我有点害怕性能,因为这只是一个对象的例子,通常我插入的对象有 20 个字段,并且在数据库中都可以为空,当然除了主键。
  • 我认为使用COALESCE() 函数不会有性能问题。使用 500K 更新和 500K 插入来插入 500K 行可能会。
  • 根据您的 DBMS(SQL-Server?什么版本?),您可能有更好的选择,一个接一个地插入/更新行。
【解决方案2】:

不要仅仅为了检查行是否存在而更新数据库

SELECT COUNT(*) FROM pde.Kun WHERE Licence=@Licence

只检查返回值是否大于 0

【讨论】:

  • 在你想要插入一行并且如果该行已经退出然后更新它的情况下,用我的方法你保存一个 sql 调用(尝试更新,如果它不影响任何行插入,这是最多 2 次调用,通常只有 1 次,因为在我的情况下重复次数很高并且更新成功),如果我使用 select count 来查找它是否存在,我将不得不进行 2 次调用,查找它是否存在,然后更新或插入
  • 但是您没有更新具有相同数据的行。 select 语句在性能方面要好得多,因为它使用表的索引来确定该行是否存在。 Similar question here 应该有帮助
猜你喜欢
  • 2020-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多