2010-06-08 2 views
0

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

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

мне нужно обновить несколько строк и присвоить 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 «s имеет проблемы с соединениями с одной и той же таблицы, обновляемой

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

ответ

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

Этот ответ был опубликован до редактирования вопроса. Это не является подходящим ответом на пересмотренный вопрос. – Hammerite