在SQL Alchemy中通过表插入多对多关联

时间:2018-08-28 11:29:11

标签: python python-3.x postgresql sqlalchemy

假设以下SQL Alchemy模型:

likes = db.Table('likes',
    db.Column('from_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
    db.Column('to_id', db.Integer, db.ForeignKey('user.id'), primary_key=True)
)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    liked_by = db.relationship('User', secondary=likes, foreign_keys=likes.c.to_id, lazy='subquery')
    likes = db.relationship('User', secondary=likes, foreign_keys=likes.c.from_id, lazy='subquery')

在多个like对象之间添加许多User关系的最快,最简单的方法是什么,如果尝试重复,该方法也不会失败?

我最接近的解决方案是:

x = [
    {'from_id': 1, 'to_id': 2},
    {'from_id': 2, 'to_id': 3},
    {'from_id': 1, 'to_id': 3},
    ...
]
stmt = likes.insert().values(x)
session.execute(stmt)
session.commit()

但是,如果例如1 -> 2已经存在,那么整个事务将失败。有什么方法可以执行此语句,从而在likes表中添加新行,而不会在现有行上失败?

该解决方案应该性能出色(即支持批量插入)。如果需要非通用答案,则数据库为PostgreSQL 10.x。

1 个答案:

答案 0 :(得分:1)

您可以使用最近添加到Postgresql中的“ upsert”功能。如果您只是想忽略重复项,请使用ON CONFLICT DO NOTHING

from sqlalchemy.dialects.postgresql import insert

stmt = insert(likes).values(x).on_conflict_do_nothing()
...