2013-07-09 5 views
0

Мне по существу нужно сделать INSERT ... ON DUPLICATE KEY UPDATE, однако строка уже будет существовать 99,9 ...% времени. Поэтому, что я действительно хочу сделать, это UPDATE, поймать нечетное исключение и INSERT.Эффективное обновление, вставка при неудаче, с sqlalchemy

В SQLAlchemy я обычно сделать следующее:

new_obj = MyModel(the_pk=id) 
new_obj = MyModel.__table__.c.some_val + val 
session.merge(new_obj) 

Я заметил, однако, что, когда я называю session.merge SQLAlchemy делает SELECT, что является неэффективным в случае, я знаю, я почти всегда UPDATE «ИНГ , Есть ли какой-то способ улучшить это, не говоря уже о написании исходного SQL (с которым я в порядке)? Мне просто интересно, есть ли какой-то трюк sqlalchemy, который мне не хватает.

Кроме того, после выполнения слияния, что произойдет, если строка с конфликтующим ПК возникнет до того, как сессия будет очищена/зафиксирована? Я предполагаю, что выбрать, чтобы определить, является ли SQLAlchemy нужно сделать позже INSERT или UPDATE

+0

Какую базу вы используете? MySQL, Postgresql, sqlite и т. Д.?? –

+0

@Tony MySQL с движком InnoDB, если он имеет значение – Endophage

ответ

1

Пара вариантов: 1) обходного SA и сделать фактическое заявление слияния или использовать КЕРЪАС если СУБД поддерживает его. Вот билет SA для добавления заявления о слиянии, который также включает в себя квитанцию ​​о замене: SA Ticket 960

2) Простой способ, сделайте обновление, вы получите количество строк, обновленных назад, если это 0, вставьте ,

У 2-го варианта могут возникнуть проблемы, если у вас есть несколько авторов, так как два писателя могут обновиться, и оба получат 0 строк, обновленных назад, и тогда только одна из двух вставк писателей будет выполнена. Не уверен, что это проблема в вашем случае, но что-то, о чем нужно знать.

+0

Учитывая MySQL, мы пытаемся избежать «INSERT ... ON DUPLICATE KEY ...», потому что он сначала пытается вставить вставить, и строка почти всегда будет существовать так, это неэффективно. Я прошел второй маршрут и добавил «исключить IntegrityError», чтобы смягчить состояние гонки при создании. – Endophage

+0

@ Энофаг - это то, что я тоже буду делать. Если удаление разрешено, вам нужно сделать что-то вроде 'while True: {try: update() else: break}', потому что несколько авторов/удалений могли бы сделать для произвольного количества IntegrityErrors, прежде чем вы на самом деле добьетесь успеха. – Phob

Смежные вопросы