假设有一个完全填充的数据数组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:
编辑:重新开启,因为这似乎是一个受欢迎的问题
答案 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将它们组合在一起。
然后,当然,你执行这一个字符串。