如何仅在不同列的值为 false、null 或与传入值不匹配且传入值设置为 true 时更新列?

How do I update a column only if a different column's value is false, null or doesn't match the incoming value and the incoming value is set to true?

在我的 table 中有两列

ClosedDate DateTime null
IsClosed bit null

如果@IsClosed 的传入值是 true 而 IsClosed 的当前值要么是 null 要么是 false 那么我想像这样将 ClosedDate 的值更新为 GetDate()

ClosedDate = GETDATE()

这是我尝试过的方法,但没有用。

ALTER PROCEDURE[dbo].someProcedure
@IsClosed   bit,
Update dbo.Foo
SET
//Other fields to be set 
ClosedDate = CASE WHEN IsClosed = 0 OR IsClosed = NULL AND IsClosed <> @IsClosed THEN GETDATE() END,
    IsClosed = @IsClosed
WHERE myId = @myId

我哪里错了?

如果一定不能改变就把CloseDate设置为它自己,否则会设置为NULL。

UPDATE dbo.Foo
SET
    ClosedDate = CASE WHEN ISNULL(IsClosed, 0) = 0 AND IsClosed <> @IsClosed
                 THEN GETDATE()
                 ELSE ClosedDate
                 END,
    IsClosed = @IsClosed
WHERE myId = @myId

请注意,如果您只设置一列,或者如果两列必须一起更新或不一起更新,您只需将所有条件添加到 WHERE 子句即可。

UPDATE dbo.Foo
SET
    ClosedDate = GETDATE()
    IsClosed = @IsClosed
WHERE
    myId = @myId AND
    ISNULL(IsClosed, 0) = 0 AND
    IsClosed <> @IsClosed

另外,不要测试IsClosed = 0 OR IsClosed = NULL。由于 NULL 传播,这不会按预期工作。使用 ISNULL(IsClosed, 0) = 0COALESCE(IsClosed, 0) = 0(我不确定 SQL-Server 2008 是否已经知道 ISNULL)。

这里的一个问题是 @IsClosed(输入)是 0 并且 IsClosed(列)是 NULL。现有 @IsClosed <> IsClosed 可能会产生意外结果。

这应该可以满足您的需要:

ALTER PROCEDURE[dbo].someProcedure
@IsClosed   bit, @MyId int
AS
Update dbo.Foo
SET
    ClosedDate = current_timestamp
    IsClosed = @IsClosed
WHERE myId = @myId AND COALESCE(IsCosed,0) = 0 and @IsClosed = 1