Reputation: 13507
Given the following table structure, how can I change the value of primary
to 0 when a duplicate unique index is found?
CREATE TABLE `ncur` (
`user_id` INT NOT NULL,
`rank_id` INT NOT NULL,
`primary` TINYINT DEFAULT NULL,
PRIMARY KEY (`user_id`, `rank_id`),
UNIQUE (`user_id`, `primary`)
);
So, when I run a query like this:
UPDATE `ncur` SET `primary` = 1 WHERE `user_id` = 4 AND `rank_id` = 5;
When a constraint of user_id-primary
is matched, I want it to set all primary
values for user_id
to NULL
, and then complete the update query by updating the row it had found.
Upvotes: 2
Views: 1402
Reputation: 4727
I am not as much familiar with MySQL as I am with Oracle; However, I think this query should work for you:
UPDATE `ncur` a
SET `primary` = (
/* 1st Subquery */
SELECT 1 FROM (SELECT * FROM `ncur`) b
WHERE b.`user_id` = a.`user_id` AND b.`rank_id` = a.`rank_id`
AND a.`rank_id` = 5
UNION ALL
/* 2nd Subquery */
SELECT 0 FROM (SELECT * FROM `ncur`) b
WHERE b.`user_id` = a.`user_id` AND b.`rank_id` <> 5 AND a.`rank_id` <> 5
GROUP BY `user_id`
HAVING COUNT(*) = 1
)
WHERE `user_id` = 4
Justification:
The query updates all the records that have user_id = 4
.
For each of such records, primary
is set to a different value of 1, 0, or NULL, depending on the value of rank_id
in this record as well as the information regarding how many other records with the same user_id
exists in the table.
The subquery that returns the value for primary
consists of three subqueries, only one of which returns a value depending on the circumstances.
1st Subquery: This subquery returns 1
for the record with rank_id = 5
; Otherwise it returns NULL
.
2nd Subquery: This subquery returns 0
for the records with rank_id
!= 5
if there is only one such record in the table; otherwise it returns NULL
.
Please note: if the query is run while there are no records with rank_id = 5, it will still update the other records according to the rules specified above. If this is not desired, the condition in the parent query must be changed from:
WHERE `user_id` = 4
to:
WHERE `user_id` = 4 AND
EXISTS(SELECT * FROM (SELECT * FROM `ncur`) b WHERE 'rank_id` = 5)
Upvotes: 1