Another possibility not mentioned yet is to just chuck the SELECT
statement itself into a CTE then Update the CTE.
;WITH CTE
AS (SELECT T1.Col1,
T2.Col1 AS _Col1,
T1.Col2,
T2.Col2 AS _Col2
FROM T1
JOIN T2
ON T1.id = T2.id
/*Where clause added to exclude rows that are the same in both tables
Handles NULL values correctly*/
WHERE EXISTS(SELECT T1.Col1,
T1.Col2
EXCEPT
SELECT T2.Col1,
T2.Col2))
UPDATE CTE
SET Col1 = _Col1,
Col2 = _Col2
This has the benefit that it is easy to run the SELECT
statement on its own first to sanity check the results but it does requires you to alias the columns as above if they are named the same in source and target tables.
This also has the same limitation as the proprietary UPDATE ... FROM
syntax shown in four of the other answers. If the source table is on the many side of a one to many join then it is undeterministic which of the possible matching joined records will be used in the Update
(An issue that MERGE
avoids by raising an error if there is an attempt to update the same row more than once).