如何解决sqlalchemy 2.0中插入时的多对一关系?

问题描述 投票:0回答:1

我有大量数据,来自不同的采集系统。这是用 SQLalchemy 定义的 ORM:

class DataTable(Base):
    __tablename__ = "data_table"
    id: Mapped[int] = mapped_column(primary_key=True)
    system_id: Mapped[int] = mapped_column(ForeignKey("system.id"))
    system: Mapped["System"] = relationship()
    data_feature: Mapped[int] = mapped_column(String(32))


class System(Base):
    __tablename__ = "system"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(16))
    system_feature: Mapped[str] = mapped_column(String(16))

系统已经存在于数据库中。现在我想将大量数据(~200k)放在DB上。每个数据行都带有系统名称。我想在数据库上传期间将这些名称解析为相应的 ID。目前,我在客户端使用 pandas.merge 解析系统名称。我从 myData pandas.DataFrame 中删除系统名称列并重命名 id 列(源于系统表)

system_table = session.execute(select(System.id, System.name)).all()
system_table_df = pandas.DataFrame(system_table)
new_data = myData.merge(system_table_df, left_on='system_name', 
right_on='name').drop(['system_name', 'name'], axis=1)
new_data.rename(columns={'id': 'system_id'}, inplace=True)

然后我可以将数据插入数据库。

session.execute(insert(DataTable).values(myData.to_dict(orient='records'))
session.commit()

有没有办法在数据库上解析系统ID?

我尝试使用 insert().returning(),这使我非常接近,但并没有完全完成工作。我不知道如何从 myData 捕获 system_name 属性并在 where 子句中使用它。

session.execute(
insert(DataTable).values(
    system_id=select(System.id).where(System.name == "???")
).returning(DataTable), myData.to_dict(orient="records"))

另一种方法是使用 session.add(),如如何使用 sqlalchemy 创建外键引用。也没解决。

python sqlalchemy orm
1个回答
0
投票

传递一个执行查找的子查询到插入的

.values()
方法

subq = (
    sa.select(System.id).where(System.name == sa.bindparam('system')).scalar_subquery()
)

with Session.begin() as s:
    insert = sa.insert(DataTable).values(system_id=subq)
    s.execute(insert, dts)

这将发出如下 SQL:

INSERT INTO data_table (system_id, data_feature) VALUES ((SELECT system.id 
FROM system 
WHERE system.name = ?), ?)
© www.soinside.com 2019 - 2024. All rights reserved.