首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQLAlchemy 'on_conflict_do_update‘未更新

SQLAlchemy 'on_conflict_do_update‘未更新
EN

Stack Overflow用户
提问于 2018-10-23 18:51:04
回答 1查看 1.7K关注 0票数 5

我有下面的代码,我想做一个upsert:

代码语言:javascript
复制
def add_electricity_reading(
    *, period_usage, period_started_at, is_estimated, customer_pk
):
    from sqlalchemy.dialects.postgresql import insert

    values = dict(
        customer_pk=customer_pk,
        period_usage=period_usage,
        period_started_at=period_started_at,
        is_estimated=is_estimated,
    )
    insert_stmt = insert(ElectricityMeterReading).values(**values)
    do_update_stmt = insert_stmt.on_conflict_do_update(
        constraint=ElectricityMeterReading.__table_args__[0].name,
        set_=dict(
            period_usage=period_usage,
            period_started_at=period_started_at,
            is_estimated=is_estimated,
        )
    )
    conn = DBSession.connection()
    conn.execute(do_update_stmt)

    return DBSession.query(ElectricityMeterReading).filter_by(**dict(
        period_usage=period_usage,
        period_started_at=period_started_at,
        customer_pk=customer_pk,
        is_estimated=is_estimated,
    )).one()

 def test_updates_existing_record_for_started_at_if_already_exists():
    started_at = datetime.now(timezone.utc)
    existing = add_electricity_reading(
        period_usage=0.102,
        customer_pk=customer.pk,
        period_started_at=started_at,
        is_estimated=True,
    )
    started_at = existing.period_started_at
    reading = add_electricity_reading(
        period_usage=0.200,
        customer_pk=customer.pk,
        period_started_at=started_at,
        is_estimated=True,
    )

    # existing record was updated
    assert reading.period_usage == 0.200
    assert reading.id == existing.id

在我的测试中,我使用period_usage=0.102添加了一个现有记录,然后再次执行查询,但更改为period_usage=0.2。当底部的最后一个查询返回记录时,period_usage仍然是0.102。

你知道为什么会发生这种事吗?

EN

回答 1

Stack Overflow用户

发布于 2018-10-23 20:30:41

"What does the Session do?"下的“会话基础”中解释了这种行为会话持有对它已加载到称为identity map的结构中的对象的引用,因此确保在会话的生命周期内每个主键值一次只存在一个唯一的对象。您可以在自己的代码中使用以下断言来验证这一点:

代码语言:javascript
复制
assert existing is reading

您正在执行的Core insert (或update)语句不会像Query.update()那样使会话与数据库中发生的更改保持同步。为了获取新值,您可以expire唯一对象的ORM加载状态:

代码语言:javascript
复制
DBSession.expire(existing)  # or reading, does not matter

# existing record was updated
assert reading.period_usage == 0.200
assert reading.id == existing.id
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52947219

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档