SQLAlchemy 会话查询与 INSERT IGNORE

1 投票
1 回答
5891 浏览
提问于 2025-04-15 13:56

我正在尝试使用SQLAlchemy进行批量插入或更新。这是我的一段代码:

for od in clist:
    where = and_(Offer.network_id==od['network_id'],
                 Offer.external_id==od['external_id'])
    o = session.query(Offer).filter(where).first()
    if not o:
        o = Offer()
    o.network_id = od['network_id']
    o.external_id = od['external_id']
    o.title = od['title']
    o.updated = datetime.datetime.now()
    payout = od['payout']
    countrylist = od['countries']
    session.add(o)
    session.flush()

    for country in countrylist:
        c = session.query(Country).filter(Country.name==country).first()
        where = and_(OfferPayout.offer_id==o.id, 
                     OfferPayout.country_name==country)
        opayout = session.query(OfferPayout).filter(where).first()
        if not opayout:
            opayout = OfferPayout()
        opayout.offer_id = o.id
        opayout.payout = od['payout']
        if c:
            opayout.country_id = c.id
            opayout.country_name = country
        else:
            opayout.country_id = 0 
            opayout.country_name = country
        session.add(opayout)

    session.flush()

看起来我的问题在这里被提到过,http://www.mail-archive.com/sqlalchemy@googlegroups.com/msg05983.html,但我不知道如何在会话查询对象中使用“文本子句”,而且我找不到太多相关的信息(不过老实说,我也没有太多时间去搜索)。

我对SQLAlchemy还很陌生,我想代码中可能还有其他问题,除了在遇到重复键时会抛出异常。例如,我在每次处理clist时都进行一次flush(但我不知道还有什么其他方法可以获取后续OfferPayout插入中使用的o.id值)。

对于这些问题的任何指导都非常感谢。

1 个回答

3

你应该用session.merge()来处理这些事情。

同时,你也要使用对象之间的关系属性。比如上面提到的o对象,它应该有o.offerpayout这个属性,而这个属性是一个对象列表。你的offerpayout对象里有一个offerpayout.country属性,这个属性就是相关的国家对象。

所以上面的内容大概是这样的:

for od in clist:

    o = Offer()
    o.network_id = od['network_id']
    o.external_id = od['external_id']
    o.title = od['title']
    o.updated = datetime.datetime.now()
    payout = od['payout']
    countrylist = od['countries']

    for country in countrylist:
        opayout = OfferPayout()
        opayout.payout = od['payout']
        country_obj = Country()
        country_obj.name = country
        opayout.country = country_obj

        o.offerpayout.append(opayout)

     session.merge(o)
     session.flush()

只要所有的主键都正确,这个方法就能正常工作(也就是说,国家表的主键是名字)。Merge的作用就是检查主键,如果主键存在,它会把你的对象和数据库里的对象合并(同时也会处理相关的连接)。

撰写回答