ON DUPLICATE KEY UPDATE
post versione 1.2 per MySQL
Questa funzionalità è ora integrata in SQLAlchemy solo per MySQL. La risposta di somada141 di seguito ha la soluzione migliore:https://stackoverflow.com/a/48373874/319066
ON DUPLICATE KEY UPDATE
nell'istruzione SQL
Se vuoi che l'SQL generato includa effettivamente ON DUPLICATE KEY UPDATE
, il modo più semplice prevede l'utilizzo di un @compiles
decoratore.
Il codice (collegato da un buon thread sull'argomento su reddit ) per un esempio si può trovare su 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)
Ma nota che in questo approccio, devi creare manualmente append_string. Probabilmente potresti modificare la funzione append_string in modo che cambi automaticamente la stringa di inserimento in un inserto con la stringa "ON DUPLICATE KEY UPDATE", ma non lo farò qui a causa della pigrizia.
ON DUPLICATE KEY UPDATE
funzionalità all'interno dell'ORM
SQLAlchemy non fornisce un'interfaccia per ON DUPLICATE KEY UPDATE
o MERGE
o qualsiasi altra funzionalità simile nel suo livello ORM. Tuttavia, ha il session.merge()
funzione che può replicare la funzionalità solo se la chiave in questione è una chiave primaria .
session.merge(ModelObject)
prima controlla se esiste una riga con lo stesso valore di chiave primaria inviando un SELECT
query (o cercandolo localmente). In tal caso, imposta un flag da qualche parte indicando che ModelObject è già nel database e che SQLAlchemy dovrebbe utilizzare un UPDATE
interrogazione. Nota che l'unione è un po' più complicata di così, ma replica bene la funzionalità con le chiavi primarie.
Ma cosa succede se vuoi ON DUPLICATE KEY UPDATE
funzionalità con una chiave non primaria (ad esempio, un'altra chiave univoca)? Sfortunatamente, SQLAlchemy non ha tale funzione. Invece, devi creare qualcosa che assomigli a get_or_create()
di Django . Un'altra risposta StackOverflow lo copre
, e per comodità incollerò qui una versione modificata e funzionante.
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