Consider data existing in a table:
Customers
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyd | Killed |
| 2 | Shelby Hawthorn | Booked |
And rows i would like to MERGEd into the Customers table:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | name has 'e' on the end
| 2 | Shelby Blanken | Waiting | different last name
| 3 | Jessica Bogden | Waiting | totally new row
So i can come up with approximate psuedocode MERGE statement:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
And that would MERGE them:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | Last name spelling updated
| 2 | Shelby Blanken | Waiting | Last name changed
| 3 | Jessica Bogden | Waiting | New row added
But only UPDATE some rows
Except a caveat is that i don't want update any existing rows for customers who are Booked
. In other words i want the final results to be:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | updated existing row spelling
| 2 | Shelby Hawthorn | Booked | not updated because they're booked
| 3 | Jessica Bogden | Waiting | inserted new row
My first guess would for the UPDATE
to have a where clause:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHERE Status <> 'Booked' -- <--------- it's the matching row; but don't update it
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
But that's not a valid syntax.
My second guess would be to add the criteria to the ON
clause:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
AND Customers.Status <> 'Booked'
WHEN MATCHED THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHERE Status <> 'Booked' --it's the matching row; but don't update it
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
But now the row would not match, and they would get inserted under the not matched by target rule:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | updated existing row
| 2 | Shelby Hawthorn | Booked | not matched bcause booked
| 3 | Jessica Bogden | Waiting | inserted new row
| 4 | Shelby Blanden | Waiting | Mistakenly inserted because not matched by target
What's the way out of the conundrum?