Reputation: 17812
I have a table with email
and secondary_email
. email
column has a unique constraint, while secondary_email
can be repeated across rows.
I have to write a query to copy secondary_email
to email
. If there is a conflict, then ignore this row.
This query
UPDATE users SET email = secondary_email
WHERE NOT EXISTS
(SELECT 1 FROM users WHERE email=secondary_email)
still throws the error ERROR: duplicate key value violates unique constraint "users_email_key"
Users Before
+----+-------+-----------------+
| id | email | secondary_email |
+----+-------+-----------------+
| 1 | NULL | NULL |
| 2 | NULL | NULL |
| 3 | NULL | |
| 4 | NULL | [email protected] |
| 5 | NULL | [email protected] |
| 6 | NULL | [email protected] |
+----+-------+-----------------+
Users After
+----+----------------+-----------------+
| id | email | secondary_email |
+----+----------------+-----------------+
| 1 | NULL | NULL |
| 2 | NULL | NULL |
| 3 | NULL | |
| 4 | [email protected] | [email protected] |
| 5 | NULL | [email protected] |
| 6 | [email protected] | [email protected] |
+----+----------------+-----------------+
Upvotes: 1
Views: 3107
Reputation: 1270773
You need table aliases to fix your query:
UPDATE users u
SET email = u.secondary_email
WHERE NOT EXISTS (SELECT 1 FROM users u2 WHERE u2.email = u.secondary_email);
For your overall problem, check for no duplicates within the column as well:
UPDATE users u
SET email = u.secondary_email
FROM (SELECT secondary_email, COUNT(*) as cnt
FROM users u
GROUP BY secondary_email
HAVING COUNT(*) = 1
) s
WHERE s.secondary_email = u.secondary_email AND
NOT EXISTS (SELECT 1 FROM users u2 WHERE u2.email = u.secondary_email);
Or choose the first one:
UPDATE users u
SET email = u.secondary_email
FROM (SELECT u.*,
ROW_NUMBER() OVER (PARTITION BY secondary_email ORDER BY user_id) as seqnum
FROM users u
) s
WHERE s.user_id = u.user_id AND
s.seqnum = 1 AND
NOT EXISTS (SELECT 1 FROM users u2 WHERE u2.email = u.secondary_email);
Note: This will also filter out NULL
values which seems like a good idea.
Here is a db<>fiddle.
Upvotes: 1