我知道这有点晚了,但我在@Emil Wåreus给出的答案基础上构建了一个函数,可以用于任何模型(表)。
def upsert_data(self, entries, model, key):
entries_to_update = []
entries_to_insert = []
for each in session.query(model).filter(getattr(model, key).in_(entries.keys())).all():
entry = entries.pop(str(getattr(each, key)))
entries_to_update.append(entry)
for entry in entries.values():
entries_to_insert.append(entry)
session.bulk_insert_mappings(model, entries_to_insert)
session.bulk_update_mappings(model, entries_to_update)
session.commit()
entries
应该是一个字典,以主键值作为键,值应该是映射(将值与数据库列进行映射)。
model
是您想要 upsert 的 ORM 模型。
key
是表的主键。
您甚至可以使用此函数从字符串中获取要插入的表的模型。
def get_table(self, table_name):
for c in self.base._decl_class_registry.values():
if hasattr(c, '__tablename__') and c.__tablename__ == table_name:
return c
使用这个方法,你只需要将表名作为字符串传递给
upsert_data
函数即可。
def upsert_data(self, entries, table, key):
model = get_table(table)
entries_to_update = []
entries_to_insert = []
for each in session.query(model).filter(getattr(model, key).in_(entries.keys())).all():
entry = entries.pop(str(getattr(each, key)))
entries_to_update.append(entry)
for entry in entries.values():
entries_to_insert.append(entry)
session.bulk_insert_mappings(model, entries_to_insert)
session.bulk_update_mappings(model, entries_to_update)
session.commit()
INSERT … ON CONFLICT DO UPDATE
功能,效果非常好。 - GG.