Как массово обновлять базу данных mysql без дубликатов?

#mysql #sql #relational-database

#mysql #sql #реляционная база данных

Вопрос:

У меня есть база данных следующим образом

 CREATE TABLE `user_relationships` (
  `id` int(11) NOT NULL,
  `user_id` int(20) UNSIGNED NOT NULL,
  `relationship` varchar(50) NOT NULL,
  `institution_id` int(20) UNSIGNED NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  

У меня есть следующие данные

 --------------------------------------------
id | user_id | relationship | institution_id
--------------------------------------------
 1 |   12    |is_working_at |    24
--------------------------------------------  
 2 |   12    |was_working_at|    23
--------------------------------------------
 3 |   12    |was_working_at|    55
--------------------------------------------
 4 |   12    |is_trained_at |    55
--------------------------------------------
  

Теперь у меня есть сценарий, в котором я хочу объединить учреждение 55 (child_id) с учреждением 23 (parent_id). Для этого я выполняю следующий запрос

 UPDATE user_relationships 
SET institution_id='{$parent_id}' 
WHERE (
    relationship IN ('was_working_at', 'is_working_at', 'is_trained_at') AND
    institution_id = {$child_id} 
) 
  

Это работает нормально, за исключением случаев, когда между пользователем и учреждением уже существуют идентичные отношения. В этом случае я получаю сообщение об ошибке типа

SQLSTATE[23000]: нарушение ограничения целостности: 1062 повторяющихся записи ’12-was_working_at-23′ для ключа ‘user_id’

Как я могу это решить? Существует ли эффективный способ написания sql-запроса, который создаст запись только в том случае, если ранее не существовало идентичных отношений?

Ответ №1:

Вы можете ОБНОВИТЬ IGNORE:

 UPDATE IGNORE user_relationships 
SET institution_id='{$parent_id}' 
WHERE
    relationship IN ('was_working_at', 'is_working_at', 'is_trained_at') AND
    institution_id = {$child_id};
  

С модификатором IGNORE оператор update не прерывается, даже если во время обновления возникают ошибки. Строки, для которых возникают конфликты с дублированием ключа при уникальном значении ключа, не обновляются. Строки, обновленные до значений, которые могли бы вызвать ошибки преобразования данных, вместо этого обновляются до ближайших допустимых значений.

Но после этого обновления вы должны решить, что должно быть dun с не обновленными строками. Может быть, вам нужно удалить их с помощью:

 DELETE FROM user_relationships 
WHERE
    relationship IN ('was_working_at', 'is_working_at', 'is_trained_at') AND
    institution_id = {$child_id};
  

Комментарии:

1. Огромное спасибо @Slava Rozhnev. Это сработало, как и ожидалось..