Reputation: 865
I'm using sqlalchemy to do an INSERT ... ON DUPLICATE KEY UPDATE
in MySQL, and I'm trying to find the lastrowid
of the primary key that was inserted or updated.
However, when the DUPLICATE
clause is triggered, the returned lastrowid
is 0, when I expected it to be the primary key of the record that was just updated.
Minimal code to reproduce -- assume for this example that the combination of first_name
+last_name
is the unique key:
from sqlalchemy import create_engine
eng = create_engine(connection_string)
query = "INSERT INTO user (first_name, last_name) VALUES ('Jim', 'Brown') ON DUPLICATE KEY UPDATE first_name='Jim' "
record_id = eng.execute(query).lastrowid
After this runs, if there is a duplicate, then record_id
is 0 instead of the primary key value. I expect to see. How can I get the primary key of the updated row?
I've also tried inserted_primary_key
, which throws the error:
sqlalchemy.exc.InvalidRequestError: Statement is not a compiled expression construct.
Upvotes: 1
Views: 4185
Reputation: 2608
The comments hint at this but figured I'd reference a good example that shows how to do insert ... on duplicate key update
with LAST_INSERT_ID
in sqlalchemy
. Check out this gist. Lifting the code here for reference but please give the author a star.
from app import db
from sqlalchemy import func
from sqlalchemy.dialects.mysql import insert
def upsert(model, insert_dict):
"""model can be a db.Model or a table(), insert_dict should contain a primary or unique key."""
inserted = insert(model).values(**insert_dict)
upserted = inserted.on_duplicate_key_update(
id=func.LAST_INSERT_ID(model.id), **{k: inserted.inserted[k]
for k, v in insert_dict.items()})
res = db.engine.execute(upserted)
return res.lastrowid
Note that inserted_primary_key
also works for me with this approach.
Upvotes: 3