如何避免在“匹配时更新”子句中重复相同的条件?

Rai*_*olt 5 sql-server update merge

我想将一张表合并到另一张表中。我需要在我的 WHEN MATCHED 子句中应用条件逻辑,理想情况下这样做:

MERGE INTO ATable AS a
USING BTable AS b
ON a.ID = b.ID
WHEN NOT MATCHED THEN
-- Do insert
WHEN MATCHED AND b.NeedsAdjustment = 1 THEN
UPDATE SET
    Col1 = b.Col1 + b.Adjustment
    ,Col2 = b.Col2 + b.Adjustment
    ,Col3 = b.Col3 + b.Adjustment
WHEN MATCHED THEN -- Default case (b.NeedsAdjustment <> 1)
UPDATE SET
    Col1 = b.Col1
    ,Col2 = b.Col2
    ,Col3 = b.Col3
Run Code Online (Sandbox Code Playgroud)

这不是有效的 SQL。根据 MSDN 文档:

如果有两个 WHEN MATCHED 子句,则一个必须指定 UPDATE 操作,一个必须指定 DELETE 操作。

这导致我进行以下查询:

MERGE INTO ATable AS a
USING BTable AS b
ON a.ID = b.ID
WHEN NOT MATCHED THEN
-- Insert happens here
WHEN MATCHED THEN
UPDATE SET
    Col1 = CASE WHEN b.NeedsAdjustment = 1 THEN b.Col1 ELSE b.Col1 + b.Adjustment END
    ,Col2 = CASE WHEN b.NeedsAdjustment = 1 THEN b.Col2 ELSE b.Col2 + b.Adjustment END
    ,Col3 = CASE WHEN b.NeedsAdjustment = 1 THEN b.Col3 ELSE b.Col3 + b.Adjustment END
Run Code Online (Sandbox Code Playgroud)

将条件逻辑移到更新内部以避开合并只能有一个WHEN MATCHED THEN UPDATE子句这一事实。现在,不是每行一张支票,而是每列每行一张支票(并且比示例中的三列多得多)。

我可以避免对需要更新的每一列重复此条件吗?有没有更好的方法来进行可能不涉及合并的条件更新?

Zan*_*ane 7

MERGE由于此处列出的所有原因,我建议首先避免使用标准更新语句。

UPDATE A 
SET
    Col1 = b.Col1 + b.Adjustment
    ,Col2 = b.Col2 + b.Adjustment
    ,Col3 = b.Col3 + b.Adjustment
FROM ATable as A
inner Join TableB as B
    ON a.ID = b.ID
    AND b.NeedsAdjustment = 1
;
UPDATE A 
SET
    Col1 = b.Col1 
    ,Col2 = b.Col2
    ,Col3 = b.Col3
FROM ATable as A
inner Join TableB as B
    ON a.ID = b.ID
AND b.NeedsAdjustment <> 1
--Or INSNUL(NeedsAdjustment,0) If it's a nullable column
;
Run Code Online (Sandbox Code Playgroud)

从长远来看,这将是一种比使用MERGE. 我还添加了 ,<>因为如果不存在,您UPDATE将覆盖第一个UPDATE.

  • @ypercube 我没有为此做出假设。既然他的原作已经注释掉了。据我所知,`NULL` 是反对 OP 的宗教的。 (3认同)

Dav*_*ave 4

MERGE是一个方便的声明,但在这种情况下受到限制。我建议简单地分解您的查询,以便您可以完全覆盖您的逻辑。如果您期望或要求该MERGE语句将在单个事务中执行其操作,您可以围绕您的逻辑声明一个显式事务:

BEGIN TRAN
INSERT
WHERE

UPDATE
WHERE

UPDATE
WHERE

COMMIT TRAN
Run Code Online (Sandbox Code Playgroud)