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