Python MySQLdb: обновить, если существует, иначе вставить - PullRequest
2 голосов
/ 26 ноября 2009

Я ищу простой способ запросить обновление или вставку, основываясь на том, существует ли строка в первую очередь. Я пытаюсь использовать MySQLdb Python прямо сейчас. Вот как я выполняю свой запрос:

self.cursor.execute("""UPDATE `inventory`
                          SET `quantity` = `quantity`+{1}
                        WHERE `item_number` = {0}
                    """.format(item_number,quantity));

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

  1. ДУБЛИКАТНЫЙ КЛЮЧ. К сожалению, первичный ключ уже используется как уникальный идентификатор, поэтому я не могу его использовать.

  2. REPLACE. Как и выше, я полагаю, что для правильной работы требуется первичный ключ.

  3. mysql_affected_rows(). Обычно вы можете использовать это после обновления строки, чтобы увидеть, было ли что-нибудь затронуто. Я не верю, что MySQLdb в Python поддерживает эту функцию.

  4. Конечно, последнее усилие по канаве: Сделайте запрос SELECT, загрузите, затем обновите или вставьте, основываясь на результате. По сути, я просто пытаюсь свести запросы к минимуму, поэтому 2 запроса вместо 1 сейчас не идеальны.

По сути, мне интересно, если я пропустил какой-либо другой способ сделать это, прежде чем перейти к варианту 4. Спасибо за ваше время.

1 Ответ

2 голосов
/ 26 ноября 2009

Mysql DOES позволяет вам иметь уникальные индексы, а INSERT ... ON DUPLICATE UPDATE выполнит обновление, если какой-либо уникальный индекс имеет дубликат, а не только PK.

Тем не менее, я бы, вероятно, все равно выбрал подход "два запроса". Вы делаете это в транзакции, верно?

  1. сделать обновление
  2. Проверьте затронутые строки, если это 0, тогда вставьте

OR

  1. Попытка вставки
  2. Если произошел сбой из-за нарушения уникального индекса, выполните обновление (NB. Вы захотите проверить код ошибки, чтобы убедиться, что он не вышел из строя по какой-либо другой причине)

Первый вариант хорош, если строка обычно уже существует, но может вызвать состояние гонки (или тупика), если вы делаете это вне транзакции или если ваш режим изоляции недостаточно высок.

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

...