MySQL: обновление строки и удаление оригинала на случай, если он станет дубликатом - PullRequest
0 голосов
/ 08 июня 2010

У меня есть простой 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-код части запроса), но помните, что мне приходится выполнять эту операцию обновления много миллионов раз.

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

Silvio

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

РЕДАКТИРОВАТЬ : извините, неверно имя столбца в предложении WHERE, теперь я исправил его

Ответы [ 2 ]

3 голосов
/ 08 июня 2010

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

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. В идеале вы должны делать все это внутри транзакции, чтобы избежать ситуации, когда проблемные строки повторно вставляются между двумя запросами.

1 голос
/ 08 июня 2010

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

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...