Sql server 使用它更新列';s当前值

Sql server 使用它更新列';s当前值,sql-server,optimization,Sql Server,Optimization,我有一个存储过程,它应该有条件地更新同一个表中的一组字段。有条件地,因为对于每个字段,我还传递一个“脏”标志,并且只有当标志设置为1时,才应该更新字段 因此,我将执行以下操作: create proc update @field1 nvarchar(1000), @field1Dirty bit, ...other fields... as begin update mytable set field1 = case when @field1dirty = 1 then @f

我有一个存储过程,它应该有条件地更新同一个表中的一组字段。有条件地,因为对于每个字段,我还传递一个“脏”标志,并且只有当标志设置为1时,才应该更新字段

因此,我将执行以下操作:

create proc update 
@field1 nvarchar(1000), @field1Dirty bit, ...other fields...
as 
begin
    update mytable
    set field1 = case when @field1dirty = 1 then @field1 else field1 end,
    ... same for other fields
end 
go

问题-SQL Server(2008)是否足够聪明,可以在字段被分配了自己的值时不进行物理更新,如@field1dirty=0?

SQL在写入之前不检查该值。它无论如何都会覆盖它

字段(如果已分配自己的字段) 值,如@field1dirty的情况= 0

不,您应该添加一个where子句,该子句说明…
where字段是您要更新到的值

一开始这似乎不是什么大问题,但事实上,它会产生大量的开销。举个例子,想想触发器。如果这更新了表中的每个字段,那么该触发器将为每一行触发。YIKES,这是很多不必要的代码执行,特别是如果代码是这样的话,比如说,将更新行移动到日志表中。我相信你明白了

请记住,在更新字段时,它恰好与以前的值相同。这实际上是好事,因为这意味着您仍然可以将字段计算为已修改的字段(想想时间戳等)。如果它不认为将字段更新为相同的值就是修改行,那么您就不会知道是否有人无意(或故意)试图更改数据

因评论而更新: 链接到

例如: 用于处理存储过程中的空参数值

Update Table SET My_Field = COALESCE(@Variable, My_Field)

这并没有绕过我之前所说的字段被更新为相同值的问题,但它允许您检查参数并有条件地更新字段。

SQL Server将执行更新。该行将作为整行更新,因此,如果该行中有一列的FieldxDirty=1,则仍需要更新。在SET子句中没有得到优化


@凯文的回答将比优化SET子句更有帮助。

很抱歉带着一个观点来到这里,但我没有其他地方可以写:-) 至少应该有一种“提示”的可能性来告诉UPDATE语句通常不更新为相同的值

我至少可以想到两个原因: 第一:要更新的值可能是一个复杂的表达式,在WHERE子句中再次表达它会浪费执行时间(更不用说维护表达式更改)。还要考虑空值! 例如:更新X集合A=B,其中为空(A“”)为空(B“”)


第二:我们有一个同步镜像场景,“备份”服务器实际放置在城市的另一部分。这意味着,当备份服务器执行写入操作时,将首先提交对磁盘的写入。写和跳写之间存在巨大的时间差。当开发人员创建应用程序时,他们在没有镜像的测试环境中工作。大多数UPDATE语句只是没有更改值,但在测试环境中这并不重要。在使用镜像将应用程序分散到生产环境之后,我们非常希望得到“仅更改值”的提示。读取原始值并检查它与写入相比并不需要时间,这是一个好的观点,但我确实希望人们不要到处放置触发器!我也是,但这是我能马上想到的最简单的例子,让我明白了这一点。不能添加where子句,因为事实上,一次更新中有多个字段——正如我所说,所示的情况是最简单的。我想我必须使用动态sqlthen@Andrey-您仍然可以使用
,其中
只需用
。SQL Server一次写入一整行,因此,如果满足任何条件,它将以任何方式重写整行,并且不会影响性能。
Update Table SET My_Field = COALESCE(@Variable, My_Field)