PO AKTUALIZACJI ZDUPLIKOWANEGO KLUCZA
post wersja 1.2 dla MySQL
Ta funkcjonalność jest teraz wbudowana w SQLAlchemy tylko dla MySQL. Odpowiedź somada141 poniżej ma najlepsze rozwiązanie:https://stackoverflow.com/a/48373874/319066
PO AKTUALIZACJI ZDUPLIKOWANEGO KLUCZA
w instrukcji SQL
Jeśli chcesz, aby wygenerowany kod SQL faktycznie zawierał ON DUPLICATE KEY UPDATE
, najprostszy sposób polega na użyciu @compiles
dekorator.
Kod (link z dobrego wątku na temat na reddit ) na przykład można znaleźć na 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)
Pamiętaj jednak, że w tym podejściu musisz ręcznie utworzyć append_string. Prawdopodobnie mógłbyś zmienić funkcję append_string, aby automatycznie zmieniała wstawiany ciąg na wstawkę z ciągiem „ON DUPLICATE KEY UPDATE”, ale nie zrobię tego tutaj z powodu lenistwa.
PO AKTUALIZACJI ZDUPLIKOWANEGO KLUCZA
funkcjonalność w ramach ORM
SQLAlchemy nie zapewnia interfejsu do ON DUPLICATE KEY UPDATE
lub MERGE
lub jakakolwiek inna podobna funkcja w swojej warstwie ORM. Niemniej jednak ma session.merge()
funkcja, która może replikować funkcjonalność tylko wtedy, gdy dany klucz jest kluczem podstawowym .
session.merge(ModelObject)
najpierw sprawdza, czy istnieje wiersz z tą samą wartością klucza podstawowego, wysyłając SELECT
zapytanie (lub wyszukując je lokalnie). Jeśli tak, ustawia gdzieś flagę wskazującą, że ModelObject jest już w bazie danych i że SQLAlchemy powinien użyć UPDATE
zapytanie. Zauważ, że scalanie jest nieco bardziej skomplikowane niż to, ale dobrze replikuje funkcjonalność z kluczami podstawowymi.
Ale co, jeśli chcesz WŁĄCZYĆ AKTUALIZACJĘ ZDUPLIKOWANEGO KLUCZA
funkcjonalność z kluczem innym niż podstawowy (na przykład inny klucz unikalny)? Niestety, SQLAlchemy nie posiada takiej funkcji. Zamiast tego musisz stworzyć coś, co przypomina get_or_create()
Django . Kolejna odpowiedź StackOverflow obejmuje to
, a dla wygody po prostu wkleję tutaj zmodyfikowaną, działającą wersję.
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