And*_*rey 15 sql t-sql sql-server sql-update
我有一张桌子:
Message (MessageID int, Subject nvarchar(100), Body nvarchar(max))
Run Code Online (Sandbox Code Playgroud)
在UI上更新消息后,我调用存储过程来更新该表.在某些情况下,用户可能只更新主题,在其他情况下只是正文.我希望这个存储过程仅更新已更改的内容,因此我还会传递标记,显示主题或正文是否已更新:
create proc UpdateMessage(
@MessageID int,
@Subject nvarchar(100),
@Body nvarchar(max),
@SubjectChanged bit,
@BodyChanged bit)
Run Code Online (Sandbox Code Playgroud)
现在我很困惑如何构建条件UPDATE
语句.我的第一个想法是使用CASE
:
Update [Message]
SET
CASE WHEN @SubjectChanged = 1 THEN [Subject] = @Subject ELSE 1=1 END,
CASE WHEN @BodyChanged = 1 THEN Body = @Body ELSE 1=1 END,
WHERE MessageID = @MessageID
Run Code Online (Sandbox Code Playgroud)
......但这似乎不是一个正确的语法,因为CASE
它必须是一个分配的右侧.
任何想法我怎么能这样做?(请记住,实际上有6个参数可以更新,而不是两个)
Ral*_*lle 27
创建语句所需的语法是:
Update [Message]
SET [Subject] = CASE WHEN @SubjectChanged = 1 THEN @Subject ELSE [Subject] END,
Body = CASE WHEN @BodyChanged = 1 THEN @Body ELSE Body END
WHERE MessageID = @MessageID
Run Code Online (Sandbox Code Playgroud)
如果你仍然想在所有建议之后坚持下去.
Nb,如果省略CASE语句的ELSE [Subject]部分,而不是忽略UPDATE,它将字段设置为NULL.
到目前为止,您最好的选择是使用明确的IF语句:
IF @subjectHasChanged = 1 and @bodyHasChanged = 1
UPDATE Messages SET Subject = @subject, Body = @body
WHERE MessageId = @MessageId
ELSE IF @subjectHasChanged = 1
UPDATE Messages SET Subject = @subject WHERE MessageId = @MessageId
ELSE IF @bodyHasChanged
UPDATE Messages SET Body = @body WHERE MessageId = @MessageId
Run Code Online (Sandbox Code Playgroud)
从性能的角度来看,没有什么比这更好的了.因为SQL在查询编译期间可以看到您只更新Body或Subject或两者,它可以生成适当的计划,例如甚至不打开(更新)您在Subject上的非聚集索引(如果您有一个,当然)当你只更新Body.
从代码质量的角度来看,这是灾难,维持的噩梦.但承认问题是80%解决问题:).例如,您可以使用代码生成技术来维护此类问题过程.
另一种可行的方法实际上是使用动态SQL,在过程中构造UPDATE并使用sp_executesql.它有自己的一组问题,就像所有动态SQL一样.有关于动态SQL问题的资源,有解决方法和解决方案,请参阅动态SQL的诅咒和祝福.
update Message set
Subject = (case when @SubjectChanged = 1 then @Subject else Subject end),
Body = (case when @BodyChanged = 1 then @Body else Body end)
where MessageID = @MessageID
Run Code Online (Sandbox Code Playgroud)
这应该就是你所需要的.但是,如果您确实无法更新字段(如果它没有更改),那么您必须在单独的语句中执行此操作.
if @SubjectChanged = 1
update Message set Subject = @Subject where MessageID = @MessageID
if @BodyChanged = 1
update Message set Body = @Body where MessageID = @MessageID
Run Code Online (Sandbox Code Playgroud)