ON DUPLICATE KEY UPDATE
publicar la versión 1.2 para MySQL
Esta funcionalidad ahora está integrada en SQLAlchemy solo para MySQL. La respuesta de somada141 a continuación tiene la mejor solución:https://stackoverflow.com/a/48373874/319066
ON DUPLICATE KEY UPDATE
en la instrucción SQL
Si desea que el SQL generado incluya realmente ON DUPLICATE KEY UPDATE
, la forma más sencilla implica usar un @compiles
decorador.
El código (enlazado desde un buen hilo sobre el tema en reddit ) para ver un ejemplo, se puede encontrar en 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)
Pero tenga en cuenta que en este enfoque, debe crear manualmente append_string. Probablemente podría cambiar la función append_string para que cambie automáticamente la cadena de inserción en una inserción con la cadena 'ON ACTUALIZACIÓN DE CLAVE DUPLICADA', pero no voy a hacer eso aquí debido a la pereza.
ON DUPLICATE KEY UPDATE
funcionalidad dentro del ORM
SQLAlchemy no proporciona una interfaz para ON DUPLICATE KEY UPDATE
o MERGE
o cualquier otra funcionalidad similar en su capa ORM. Sin embargo, tiene el session.merge()
función que puede replicar la funcionalidad solo si la clave en cuestión es una clave principal .
session.merge(ModelObject)
primero comprueba si existe una fila con el mismo valor de clave principal enviando un SELECT
consulta (o buscándola localmente). Si lo hace, establece una marca en algún lugar que indica que ModelObject ya está en la base de datos y que SQLAlchemy debe usar UPDATE
consulta. Tenga en cuenta que fusionar es un poco más complicado que esto, pero replica bien la funcionalidad con claves principales.
Pero, ¿qué sucede si desea ON DUPLICATE KEY UPDATE
? funcionalidad con una clave no primaria (por ejemplo, otra clave única)? Desafortunadamente, SQLAlchemy no tiene esa función. En su lugar, debe crear algo que se asemeje a get_or_create()
de Django. . Otra respuesta de StackOverflow lo cubre
, y simplemente pegaré una versión funcional modificada aquí para mayor comodidad.
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