ON DUPLICATE KEY UPDATE
post-1.2 для MySQL
Эта функциональность теперь встроена только в SQLAlchemy для MySQL.Ответ somada141 ниже имеет лучшее решение: https://stackoverflow.com/a/48373874/319066
ON DUPLICATE KEY UPDATE
в операторе SQL
Если вы хотите, чтобы сгенерированный SQL действительно включал ON DUPLICATE KEY UPDATE
, самый простой способ заключается в использовании @compiles
decorator.
Код (связанный с хорошей веткой по теме на reddit ) для примера можно найти на github :
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import Insert
@compiles(Insert)
def append_string(insert, compiler, **kw):
s = compiler.visit_insert(insert, **kw)
if 'append_string' in insert.kwargs:
return s + " " + insert.kwargs['append_string']
return s
my_connection.execute(my_table.insert(append_string = 'ON DUPLICATE KEY UPDATE foo=foo'), my_values)
Но учтите, что при таком подходе вы должны вручную создать строку append_string.Возможно, вы могли бы изменить функцию append_string, чтобы она автоматически изменяла строку вставки на вставку со строкой «ON DUPLICATE KEY UPDATE», но я не собираюсь делать это здесь из-за лени.
ON DUPLICATE KEY UPDATE
функциональность в ORM
SQLAlchemy не предоставляет интерфейс для ON DUPLICATE KEY UPDATE
или MERGE
или любой другой аналогичной функциональности на своем уровне ORM.Тем не менее, он имеет функцию session.merge()
, которая может воспроизводить функциональность , только если рассматриваемый ключ является первичным ключом .
session.merge(ModelObject)
, сначала проверяет, является лиСтрока с тем же значением первичного ключа существует путем отправки запроса SELECT
(или локального поиска).Если это так, он устанавливает флаг где-то, указывая, что ModelObject уже находится в базе данных, и что SQLAlchemy должен использовать запрос UPDATE
.Обратите внимание, что слияние немного сложнее, чем это, но оно хорошо копирует функциональность с первичными ключами.
Но что, если вам нужна функциональность ON DUPLICATE KEY UPDATE
с неосновным ключом (например, другой уникальный ключ))?К сожалению, в SQLAlchemy такой функции нет.Вместо этого вы должны создать что-то, что напоминает Django get_or_create()
. Другой ответ StackOverflow охватывает это , и я просто вставлю сюда модифицированную рабочую версию для удобства.
def get_or_create(session, model, defaults=None, **kwargs):
instance = session.query(model).filter_by(**kwargs).first()
if instance:
return instance
else:
params = dict((k, v) for k, v in kwargs.iteritems() if not isinstance(v, ClauseElement))
if defaults:
params.update(defaults)
instance = model(**params)
return instance