Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在不违反约束的情况下跨多行更新唯一受约束列中的数据?_Sql_.net_Sql Server_Wpf_Vb.net - Fatal编程技术网

Sql 如何在不违反约束的情况下跨多行更新唯一受约束列中的数据?

Sql 如何在不违反约束的情况下跨多行更新唯一受约束列中的数据?,sql,.net,sql-server,wpf,vb.net,Sql,.net,Sql Server,Wpf,Vb.net,我有一个带有唯一约束的列的表。用户将以绑定到DataGrid的DataTable的形式编辑此表中的数据。修改完数据后,save函数必须将其更改应用回数据库。出于应用程序体系结构的原因,对数据库的每次更改都必须作为创建、更新或删除操作一次执行一行。我可以验证DataTable以确保最终结果不会违反约束,但似乎无法验证在这两者之间是否永远不会违反约束。即使我不允许在DataGrid本身内部重复值,用户也可以在进行违反约束的修改时放入占位符值,DataTable类似乎只存储每行的原始和最终版本,而不是

我有一个带有唯一约束的列的表。用户将以绑定到DataGrid的DataTable的形式编辑此表中的数据。修改完数据后,save函数必须将其更改应用回数据库。出于应用程序体系结构的原因,对数据库的每次更改都必须作为创建、更新或删除操作一次执行一行。我可以验证DataTable以确保最终结果不会违反约束,但似乎无法验证在这两者之间是否永远不会违反约束。即使我不允许在DataGrid本身内部重复值,用户也可以在进行违反约束的修改时放入占位符值,DataTable类似乎只存储每行的原始和最终版本,而不是中间版本


如何在对数据进行这些更改时避免任何唯一的约束冲突?

最简单的方法是更新SQL语句中的所有约束值:

UPDATE [Foo] Set [SomeUniqueValue] = CASE [ID] WHEN 1 THEN 'A' WHEN 2 THEN 'B' WHEN 3 THEN 'C' END WHERE [ID] IN (1,2,3)
如果交换前后的值,这不会违反唯一性,只要语句完成时保持唯一性

如果您必须一次执行一行,则可能必须强制运行更新列表,在更新失败时捕获错误,并在循环中不断重试出错的更新,直到所有更新完成,否则无法进行更多更新:

bool didSomething;
List<Row> rowsThatNeedToTryAgain = new List<Row>();
do {
   didSomething = false;
   rowsThatNeedToTryAgain.Clear();
   foreach (Row row in rowsToUpdate) {
      try {
         UpdateTheRowInTheDatabase(row);
         didSomething = true;
      } catch {
         rowsThatNeedToTryAgain.Add(row);
      }
   }
   rowsToUpdate.Clear();
   rowsToUpdate.AddRange(rowsThatNeedToTryAgain);
} while (didSomething && rowsThatNeedToTryAgain.Count > 0);

if (rowsThatNeedToTryAgain.Count > 0) 
   throw new Exception("sorry, couldn't do 'em all");
bool做了些什么;
List ROWSTHATNEEDTOTRYREALE=新列表();
做{
做某事=错误;
需要重试的行。清除();
foreach(rowsToUpdate中的行){
试一试{
更新数据库(行);
做某事=真实;
}抓住{
需要重试的行。添加(行);
}
}
rowsToUpdate.Clear();
rowsToUpdate.AddRange(需要再次刷新的行);
}while(做了需要再次做的事情(&rowst)。计数>0);
如果(需要再次计时的行。计数>0)
抛出新异常(“抱歉,无法全部执行”);
一个更优雅的解决方案可以在不影响数据库的情况下从代码中执行此操作,但这将假定您的进程是当时唯一更新的进程