即使数据未更新,MERGE语句也会更新

时间:2019-03-06 09:43:36

标签: sql-server tsql merge

我有一个merge语句,如果其中任何列的值不同,我想在其中更新表行。但是,即使即使源表中的大多数行都保持不变,MERGE语句也至少在计算UPDATE的执行量时执行UPDATE

DECLARE @SummaryOfChanges TABLE(Change VARCHAR(50));

MERGE MyTarget AS TARGET
USING MySource AS SOURCE
ON (SOURCE.customeridHash = TARGET.Id)
WHEN MATCHED AND (TARGET.IsCompany <> SOURCE.company
    OR TARGET.Gender <> SOURCE.gender
    OR TARGET.BirthDate <> CONVERT(DATE, SOURCE.dateofbirth)
    OR TARGET.ZipCode <> SOURCE.ZipCode
    OR TARGET.City <> SOURCE.City
    OR TARGET.WantsEmail <> (CASE WHEN SOURCE.noemail = 0 THEN 1 ELSE 0 END)
    OR TARGET.WantsSMS <> (CASE WHEN SOURCE.nosms = 0 THEN 1 ELSE 0 END)
    OR TARGET.WantsDM <> (CASE WHEN SOURCE.nodirectmarketing = 0 THEN 1 ELSE 0 END)
    OR TARGET.WantsTM <> (CASE WHEN SOURCE.notelemarketing = 0 THEN 1 ELSE 0 END)
    OR TARGET.HasEmail <> SOURCE.HasEmail
    OR TARGET.HasMobilePhoneNumber <> SOURCE.HasMobilePhoneNumber
    OR TARGET.HasPhoneNumber = SOURCE.HasPhoneNumber
    OR TARGET.Created <> SOURCE.Created
    OR TARGET.Updated <> SOURCE.changed)
THEN
UPDATE SET TARGET.IsCompany = SOURCE.company,
    TARGET.Gender = SOURCE.gender,
    TARGET.BirthDate = CONVERT(DATE, SOURCE.dateofbirth),
    TARGET.ZipCode = SOURCE.ZipCode,
    TARGET.City = SOURCE.City,
    TARGET.WantsEmail = (CASE WHEN SOURCE.noemail = 0 THEN 1 ELSE 0 END),
    TARGET.WantsSMS = (CASE WHEN SOURCE.nosms = 0 THEN 1 ELSE 0 END),
    TARGET.WantsDM = (CASE WHEN SOURCE.nodirectmarketing = 0 THEN 1 ELSE 0 END),
    TARGET.WantsTM = (CASE WHEN SOURCE.notelemarketing = 0 THEN 1 ELSE 0 END),
    TARGET.HasEmail = SOURCE.HasEmail,
    TARGET.HasMobilePhoneNumber = SOURCE.HasMobilePhoneNumber,
    TARGET.HasPhoneNumber = SOURCE.HasPhoneNumber,
    TARGET.Created = SOURCE.Created,
    TARGET.Updated = SOURCE.changed
WHEN NOT MATCHED BY TARGET THEN
INSERT (
    Id, 
    IsCompany, 
    Gender, 
    BirthDate, 
    ZipCode, 
    City, 
    WantsEmail, 
    WantsSMS,
    WantsDM, 
    WantsTM, 
    HasEmail, 
    HasMobilePhoneNumber, 
    HasPhoneNumber, 
    Created, 
    Updated
)
VALUES (
    SOURCE.customeridHash,
    SOURCE.company,
    SOURCE.gender,
    CONVERT(DATE, SOURCE.dateofbirth),
    SOURCE.ZipCode,
    SOURCE.City,
    (CASE WHEN SOURCE.noemail = 0 THEN 1 ELSE 0 END),
    (CASE WHEN SOURCE.nosms = 0 THEN 1 ELSE 0 END),
    (CASE WHEN SOURCE.nodirectmarketing = 0 THEN 1 ELSE 0 END),
    (CASE WHEN SOURCE.notelemarketing = 0 THEN 1 ELSE 0 END),
    SOURCE.HasEmail,
    SOURCE.HasMobilePhoneNumber,
    SOURCE.HasPhoneNumber,
    SOURCE.Created,
    SOURCE.changed
)
WHEN NOT MATCHED BY SOURCE THEN DELETE
OUTPUT $action INTO @SummaryOfChanges;

SELECT Change, COUNT(*) CountPerChange
FROM @SummaryOfChanges
GROUP BY Change;

在更新结束时(最后一个SELECT),我做了一些记账工作,似乎几乎所有不是新的行都被更新了。这是常见的行为吗?还是在我的<>比较中,WHEN MATCHED AND...确实有更新的价值?

更新:根据其中一项评论的建议,我编写了以下测试来检查我的状况是否触发了更新:

-- TEST MERGE
select count(*) 
from MyTarget TARGET join MySource SOURCE on TARGET.Id=SOURCE.customeridHash
where TARGET.IsCompany <> SOURCE.company
    OR TARGET.Gender <> SOURCE.gender
    OR TARGET.BirthDate <> CONVERT(DATE, SOURCE.dateofbirth)
    OR TARGET.ZipCode <> SOURCE.ZipCode
    OR TARGET.City <> SOURCE.City
    OR TARGET.WantsEmail <> (CASE WHEN SOURCE.noemail = 0 THEN 1 ELSE 0 END)
    OR TARGET.WantsSMS <> (CASE WHEN SOURCE.nosms = 0 THEN 1 ELSE 0 END)
    OR TARGET.WantsDM <> (CASE WHEN SOURCE.nodirectmarketing = 0 THEN 1 ELSE 0 END)
    OR TARGET.WantsTM <> (CASE WHEN SOURCE.notelemarketing = 0 THEN 1 ELSE 0 END)
    OR TARGET.HasEmail <> SOURCE.HasEmail
    OR TARGET.HasMobilePhoneNumber <> SOURCE.HasMobilePhoneNumber
    OR TARGET.HasPhoneNumber = SOURCE.HasPhoneNumber
    OR TARGET.Created <> SOURCE.Created
    OR TARGET.Updated <> SOURCE.changed;

我意识到此查询返回相同数量的更新。因此,更多关于MERGE语句的条件。但是我不知道它们如何触发更新。

1 个答案:

答案 0 :(得分:0)

在我写的条件下,我认为我发现了自己的错误:

OR TARGET.HasPhoneNumber = SOURCE.HasPhoneNumber

几乎总是真实的!