• There's one issue with using the EXCEPT approach as the data source for a subsequent MERGE: it becomes impossible to tell from within the MERGE if rows have been deleted from the data source (as they are combined with rows that are identical across both the source and target). If that's okay (you may not care about deletes or you may know that the source never has deletes) then fine, but if not, you are left with the problem of dealing with deletes separately.

    An alternative is to use MERGE itself to do the work for you. You end up with doing the following:

    MERGE INTO B

    USING A

    ON A.key = B.key

    WHEN MATCHED AND (

    A.x is null and B.x is not null or

    A.x is not null and B.x is null or

    A.x <> B.x or

    A.y is null and B.y is not null or

    A.y is not null and B.y is null or

    A.y <> B.y

    )

    THEN -- update

    WHEN NOT MATCHED BY TARGET

    THEN -- insert

    WHEN NOT MATCHED BY SOURCE

    THEN -- delete

    Okay, so that's more code you have to write, unless you take into account the additional code you have to write to handle deletes using the other approach.

    I generally don't favour calculating a checksum across the columns and comparing checksums. SQL Server has to calculate the checksum across all of the columns every time, whereas with the column by column comparison, it can "short circuit" the comparison as soon as it finds a mis-match. If you calculate the checksum while you are loading the data, it should improve the performance of the subsequent MERGE, but at the cost of a slower load and having to store the checksum; it's a trade-off. The approach with using MERGE to determine the changes will work either way.