Reputation: 183
EDIT: This is just an simplified example, I know it seems really wrong, but thought this is the simpliest way to ask my question.
Let's say I have a Person
and an 'Email' table. Each person can have 2 e-mails.
Here is a small example:
For some reason, we decide to extend our Person
table with 2 columns: FirstEmail
, and SecondEmail
, so after an update, the results looks like something like this:
Can I UPDATE
the table with a single statement? For example, I tried this, but it doesn't work (doesn't give error, only the FirstEmail
is filled, the SecondEmail
is NULL
).
UPDATE Person
SET FirstEmail = CASE WHEN e.Type = 'FIRST' THEN e.Value ELSE FirstMail END,
SecondMail = CASE WHEN e.Type = 'SECOND' THEN e.Value ELSE SecondMail END
FROM Person p
INNER JOIN Email e ON (p.Id = e.PersonId);
And as I see MERGE
can't work with multiple rows, because I get this error for a similar approach:
The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.
Upvotes: 2
Views: 3095
Reputation: 17953
Following query should work for you.
UPDATE P
SET P.FirstEmail = F.Value,
P.SecondEmail= S.Value
FROM Person P
INNER JOIN EMAIL F ON F.PersonId=P.ID AND F.TYPE='FIRST'
INNER JOIN EMAIL S ON S.PersonId=P.ID AND S.TYPE='SECOND'
If you don't have both the emails for Person, in that case you can change the INNER JOIN
to LEFT JOIN
UPDATE P
SET P.FirstEmail = F.Value,
P.SecondEmail= S.Value
FROM Person P
LEFT JOIN EMAIL F ON F.PersonId=P.ID AND F.TYPE='FIRST'
LEFT JOIN EMAIL S ON S.PersonId=P.ID AND S.TYPE='SECOND'
Upvotes: 3
Reputation: 14209
The problem with your update attempt is that a row with a particular email is never "First" and "Second" at the same time (so either FirstEmail
is updated or SecondEmail
is, but never both).
A solution is using 2 joins, one for each email:
UPDATE P SET
FirstEmail = E1.Value,
SecondEmail = E2.Value
FROM
Person AS P
LEFT JOIN Email AS E1 ON
E1.PersonID = P.ID AND
E1.Type = 'First'
LEFT JOIN Email AS E2 ON
E2.PersonID = P.ID AND
E2.Type = 'Second'
Upvotes: 0
Reputation: 6465
Using two subqueries the solution is trivial :
update Person set
FirstEMail = (select top 1 Value from EMail where PersonId = Person.Id and Type = 'FIRST'),
SecondEMail = (select top 1 Value from EMail where PersonId = Person.Id and Type = 'SECOND')
Upvotes: 2