获取 sqlalchemy 的 upsert 中插入和更新记录的计数

Posted

技术标签:

【中文标题】获取 sqlalchemy 的 upsert 中插入和更新记录的计数【英文标题】:Get count of inserted and updated records in sqlalchemy's upsert 【发布时间】:2022-01-06 13:34:12 【问题描述】:

我有一个通过sqlalchemy 更新插入几条记录的工作代码:

from sqlalchemy.dialects.postgresql import insert

from sqlalchemy import BigInteger
from flask_sqlalchemy import SQLAlchemy as db 

class PetModel(db.Model):
  __tablename__ = "pets"

  id = db.Column(BigInteger, primary_key=True)
  data = db.Column(db.String(64), nullable=False, unique=True)

  def as_dict(self):
    return 
      "id": getattr(self, "id"),
      "data": getattr(self, "data"),
    

pets = [PetModel(id=1, data="Dog"), PetModel(id=2, data="Cat")]

insert_statement = insert(PetModel).values([_.as_dict() for _ in pets])
upsert_statement = insert_statement.on_conflict_do_update(
  constraint="pet_pkey",
  set_="data": insert_statement.excluded.data,
)
ans = db.session.execute(upsert_statement)

我试图通过将returning(PetModel.__table__) 添加到insert_statement 中来返回所有行,但是我无法将[_ for _ in ans] 语句的答案分开更新和插入。我不想在数据库中添加特殊字段。

我知道ans.rowcount 返回更新和插入记录的总和。

如何使用sqlalchemy 分别获取更新和插入记录的数量?

【问题讨论】:

xmax hack:***.com/questions/34762732/… 谢谢!这是迈向正确道路的一步。我使用这里描述的方式:***.com/a/62535477/9978223 【参考方案1】:

正如Ilja Everilä 所说,其中一个决定是使用xmax hack。

我们应该将具有此值的列添加到答案中,例如描述here

from sqlalchemy.dialects.postgresql import insert
...
insert_statement = insert(PetModel).returning(
  sqlalchemy.column("xmax") == 0
).values([_.as_dict() for _ in pets])
upsert_statement = insert_statement.on_conflict_do_update(
  constraint="pet_pkey",
  set_="data": insert_statement.excluded.data,
)
ans = db.session.execute(upsert_statement)
created = sum([_._row[0] for _ in ans])
updated = len(pets) - created

【讨论】:

以上是关于获取 sqlalchemy 的 upsert 中插入和更新记录的计数的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy Upsert无法找到表“已排除”

如何在 flask_sqlalchemy 中使用 PostgreSQL 的“INSERT...ON CONFLICT”(UPSERT)功能?

将 Oracle upsert 转换为 PostgreSQL 准备好的语句

用Python实现单链表的头插,尾插和中插

JAVA------20.图片中插文字和图片

SQLAlchemy,获取未绑定到会话的对象