MySQL: обновление строки и удаление оригинала на случай, если он станет дубликатом

0

У меня есть простой table, состоящий из двух столбцов: col_A и col_B.

Первичный ключ определяется для обоих.

Мне нужно обновить некоторые строки и присвоить значениям col_A, которые могут генерировать дубликаты, например:

UPDATE `table` SET `col_A` = 66 WHERE `col_A` = 70

Этот оператор иногда дает дубликат ключевой ошибки.

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

Я бы хотел написать что-то вроде:

UPDATE `table` SET `col_A` = 66 WHERE `col_A` = 70 ON DUPLICATE KEY REPLACE

который, к сожалению, не является законным в SQL, поэтому мне нужна помощь в поиске другого пути. Кроме того, я использую PHP и могу рассмотреть гибридное решение (т.е. Часть запроса части php-кода), но имейте в виду, что я должен выполнять эту операцию обновления много миллионов раз.

спасибо за внимание,

Сильвио

Напоминание: синтаксис UPDATE имеет проблемы с объединениями с той же таблицей, которая обновляется

EDIT: извините, имя столбца в предложении WHERE было неправильным, теперь я исправил его

Теги:
duplicates
primary-key

2 ответа

3
Лучший ответ

Ответ на пересмотренный вопрос:

DELETE FROM
    table_A
USING
    table AS table_A
    JOIN table AS table_B ON
        table_A.col_B = table_B.col_B AND
        table_B.col_A = 70
WHERE
    table_A.col_A = 66

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

  • 0
    это работает, спасибо!
1

Есть ли внешние ключи, ссылающиеся на эту таблицу? Если нет, то следующее:

CREATE PROCEDURE `MyProcedure` (IN invarA INT, IN invarB INT)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
BEGIN
    DELETE FROM table WHERE col_B = invarB;
    IF ROW_COUNT() > 0 THEN
        INSERT INTO table (`col_A`, `col_B`) VALUES (invarA, invarB);
    END IF;
END

Пример вызова:

CALL `MyProcedure`(66, 70)
  • 0
    Этот ответ был опубликован до редактирования вопроса. Это не подходящий ответ на пересмотренный вопрос.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню