[英]Using `sqlalchemy` `insert` to bulk insert related objects
我正在使用 sqlalchemy 將數據插入表中。 我關心的事情:
on_conflict_do_nothing
(我正在使用 postgres)。作為一個最小的例子,假設我有兩個表:
from sqlalchemy import Column, Integer, ForeignKey, String
Base = declarative_base()
class Address(Base):
__tablename__ = "addresses"
id = Column(Integer, primary_key=True)
street = Column(String)
number = Column(Integer)
class Person(Base)
__tablename__ = "people"
id = Column(Integer, primary_key=True)
name = Column(String)
address_id = Column(Integer, ForeignKey("addresses.id")
address = relationship("Address")
我可以通過以下方式輕松地批量處理所有Address
插入:
from sqlalchemy.dialects.postgresql import insert
values = [{"street": "main", "number": 1}, {"street": "main", "number": 2}]
statement = insert(Address).values(values).on_conflict_do_nothing()
session.execute(statement)
問題是我如何對People
做同樣的事情? 我正在為"address"
提供什么而苦苦掙扎,例如
values = [{"name": "John", "address": ????}]
statement = insert(Person).values(values).on_conflict_do_nothing()
session.execute(statement)
我假設我需要Address
object 但是我不知道 go 從那里到哪里?
不要使用address
,因為它不是 SQL 字段。 您可以使用INSERT...RETURNING來獲取您剛剛插入的地址的 ID,然后在此基礎上設置values[0]['address_id']
。 像這樣的東西應該工作:
from sqlalchemy.dialects.postgresql import insert
values = [{"street": "main", "number": 1}, {"street": "main", "number": 2}]
statement = insert(Address)\
.values(values)\
.returning(Address.id)\
.on_conflict_do_nothing()
address_ids = [address_id for address_id, in session.execute(statement)]
values = [{"name": "John", "address_id": address_ids[0]}]
statement = insert(Person).values(values).on_conflict_do_nothing()
session.execute(statement)
解釋
使用insert().on_conflict_do_nothing
,與 SQLAlchemy 的添加層相比,您將相對接近 PostgreSQL 的裸機。 這不是一件壞事,當然是你控制最多、提速最大的地方,但這確實意味着你需要仔細考慮SQLAlchemy添加了哪些字段,哪些字段直接反映在ZD233B99A3CCB7F38A032466289B6D227數據庫。
在您的情況下,只有id
、 name
和address_id
是實際的數據庫列。 如果您執行SELECT * FROM people
,它們是唯一應該顯示的列。 相反, address
是由 SQLAlchemy 添加的,以便為您提供指向 ID 為address_id
的Address
實例的直接鏈接,但在水下,如果需要,將對數據庫執行不同的調用以獲取它。
如果你有一個 id 為 1 的Address
,那么設置john.address = 1
不起作用,因為 1 不是地址,它是一個數字。 但是,設置john.address_id = 1
確實有效,因為您直接設置了一個字段。 如果您使用完整的 ORM(您不是),SQLAlchemy 不鼓勵這樣做,因為您在他們的生態系統之外執行此操作。 如果運行john.address = Address.query.get(1)
,則將整個地址 object 分配給地址,並且 SQLAlchemy 在內部將address_id
更新為 1。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.