将多行更新到SQL表中

时间:2008-10-08 18:17:37

标签: c# asp.net sql

假设有一个完全填充的数据数组String [n] [3] myData。

我想这样做:

for (String[] row : myData)
{
   SQL = "update mytable set col3 = row[2]
   where col1 = row[0] and col2=row[1];" 
}

显然我已经离开了很多,但我想尽可能简洁地表达这个想法。

在单个DB命令中有一种简单的方法吗? 一个不那么简单的方法怎么样?

编辑: 数据不是来自另一个表格(这是一个网络表单提交 - 多项选择考试)
看到应用程序是面向Web的,它必须是注入证明。参数化查询是我的首选方式 我正在使用MS-SQL Server 2005

编辑:关闭,并重新询问为Multiple DB Updates:

编辑:重新开启,因为这似乎是一个受欢迎的问题

10 个答案:

答案 0 :(得分:7)

这取决于您使用的数据库。如果您使用的是SQL Server 2008,则可以使用存储过程TABLE parameters。这允许您将所有值传递到单个表中的存储过程中,然后您可以执行以下操作:

update mytable set mytable.col1 = @tbl.col1
  from mytable 
  inner join @tbl on mytable.col2 = @tbl.col2

如果您使用的是SQL Server 2005,则可以使用XML。将值格式化为XML,然后使用XQuery语句(即“nodes”和“value”)来解析XML。这也可以在单个SQL语句中完成,并且不需要存储过程。

答案 1 :(得分:3)

如果您使用的是Sql Server,则可以使用SqlBulkCopy。您首先必须将数据放在DataTable中,这很简单,因为您已经将它放在字符串数组中。

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

答案 2 :(得分:1)

你可以创建一个大字符串:

for (String[] row : myData)
{
   SQL += "update mytable set col3 = row[2]
   where col1 = row[0] and col2=row[1];" 
}

sqlDriver.doInsertQuery(SQL); // change this to your way of inserting into the db

立即全部投入。我对SQL不是很了解,所以我会这样做。

sql引擎只会将它拆分为';'并自己单独插入。可以将它全部添加到字符串中。它类似于将一个包含多个更新/插入的大字符串复制到sql提示符中

答案 3 :(得分:1)

这可能不是您想要的答案,但是从数据库的角度来看,打开事务,执行语句然后提交事务将会执行您所描述的操作。

在事务完成之前,数据库的其他用户的数据库状态不会发生变化,这可能是首选效果。

答案 4 :(得分:1)

看起来你想要在包含B和C代码的行上创建更新A.(A,B,C)在myData中存储为元组(行)。不是吗?

也许(如果你使用的是Microsoft SQL Server ......我不知道它是否存在于Oracle中,可能是)你可以使用带有UPDATE的JOIN。您可以在与另一个表连接的表上声明更新。如果myData来自另一个表,那么你可以做(​​这不是正确的语法):

UPDATE whatchanges wc INNER JOIN changes c ON <yourcondition>
SET wc.col1 = c.newvalue
WHERE ....

(如果你想在“更改”表中应用所有更改,你当然不必使用WHERE,INNER JOIN已经选择了正确的行。)

当然这种更新存在局限性。它是MS SQL专有的。所以,如果是你的情况,我建议在MS网站上寻找它(关键字:UPDATE和JOIN)

答案 5 :(得分:1)

如果您在数据访问层中使用Enterprise Library,则可以在.Net中创建事务,遍历您的过程调用,然后从.Net提交/回滚。

DbTransaction transaction = connection.BeginTransaction();
try
{
    for (String[] row : myData)
    {
        ListDictionary params = new Specialized.ListDictionary();
        params.add("@col3", row[2]);
        params.add("@col1", row[0]);
        params.add("@col2", row[1]);
        executeNonQuery("myUpdateProcedure", params);
    }

    transaction.commit();

}
catch(Exception ex)
{
    transaction.rollback();
    throw ex;
}
finally
{

    connection.close();
}

答案 6 :(得分:1)

如果由于某种原因您无法使用上面建议的方法之一执行更新,下面的低效率方法可能对您有用。

SQL = "Update myTable Set Col3 = Case " 
for (String[] row : myData)
{
   SQL += "When Col1 = " + Row[0] + " and Col2 = " + Row[1] + " then " + row[2] + " "   
}
SQL + = "Else Col3 end"  

答案 7 :(得分:0)

不是真的。您可以使用相同的循环创建字符串,然后将您的值作为参数传递,但这仍然是多个数据库命令。

for each whatever
    sql += "UPDATE ... ;"
end for
execute (sql)

答案 8 :(得分:0)

我怀疑你需要使用多个SQL语句。你可能会找到一个处理细节的包装器,但在下面我想象它会为每个UPDATE迭代运行一个SQL语句。

答案 9 :(得分:0)

发出违反值表的更新:

UPDATE myTable SET col3=c FROM myTable JOIN (
  SELECT 1 as a, 2 as b, 'value1' as c UNION ALL
  SELECT 3 as a, 4 as b, 'value2' as c -- etc...
) x ON myTable.col1=x.a AND myTable.col2=x.b

所以你就这样把它放在一起:

// make one of these for each row
String.Format("SELECT {0} as a, {1} as b, '{2}' as c", 
  row[0], row[1], row[2].Replace("'","''")) 

// put it together
string expr = "UPDATE myTable SET col3=c FROM myTable JOIN (" +
  String.Join(stringformatarray, " UNION ALL ") +
  ") x ON myTable.col1=x.a AND myTable.col2=x.b"

或者您可以使用StringBuilder将它们组合在一起。

然后,当然,你执行这一个字符串。