2012-01-24 39 views
3

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

这里是我怎么做,现在一个简单的例子:

private const string UpdateKun = "UPDATE pde.Kun SET [email protected] WHERE [email protected]"; 
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; 
     } 
    } 
+0

一些SQL产品具有的功能你用一个语句描述:'INSERT ... IF DUPLICATE UPDATE ...'因为它是一个 –

+0

@ypercube 'SqlCommand'它的SQL Server。那么它会合并,只要它2005年或更大 –

+0

是啊我没有真正进入SQL,但我会认为它应该有这样的功能:)我使用Sql server 2008,express版,我会查找MERGE语法,谢谢 – MSkuta

回答

2

更改更新到:

UPDATE pde.Kun 
SET [email protected] 
WHERE [email protected] 
    AND @Jmeno IS NOT NULL 

如果你有一个以上的栏目更新:

UPDATE pde.Kun 
SET Jmeno = COALESCE(@Jmeno, Jmeno) 
    , ColumnB = COALESCE(@ColumnB, ColumnB) 
WHERE [email protected] 
+0

好主意,看起来像解决方案,甚至认为我有点害怕表现,因为这只是一个对象的例子,通常我插入的对象有20个字段,并且除了课程的主键之外,所有对象都可以为null。 – MSkuta

+0

我想,使用'COALESCE()'函数不会有性能问题。尽管可以使用500K更新和500K插入插入500K行。 –

+0

根据你的DBMS(SQL-Server?什么版本?),你可能会有更好的选择来插入/更新行,一个接一个。 –

0

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

SELECT COUNT(*) FROM pde.Kun WHERE [email protected] 

,只是检查返回值大于0

+0

或者使用If EXISTS –

+0

那么在需要插入行的情况下,如果行已经存在,然后更新它,使用我的方法可以保存一个sql调用(如果更新不起作用任何行插入它,这是最大2调用,通常只有1,因为在我的情况和更新成功高重复),如果我使用选择计数来找到它是否存在我将不得不做2个呼叫,找到如果存在,则更新或插入 – MSkuta

+0

但是,您没有更新具有相同数据的行。由于select语句使用表索引来确定该行是否存在,因此select语句的性能更好。 [类似问题在这里](http://stackoverflow.com/questions/6696063/select-vs-update-performance-with-index)应该帮助 – Kypros