You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pandas和SQLAlchemy导入Excel实现PostgreSQL一对多数据插入?

解决PostgreSQL一对多关系的批量插入问题

针对你遇到的一对多数据插入需求,这里提供两种可行方案,根据数据量大小选择即可:

方案一:逐行ORM插入(适合小数据量)

直接利用SQLAlchemy的ORM会话,逐行处理Excel数据,插入Body后立即获取ID,再关联插入标签。这种方式逻辑简单,不需要依赖额外唯一标识,适合数据量不大的场景。

假设你的SQLAlchemy模型如下(和你已配置的一致):

from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

Base = declarative_base()

class Body(Base):
    __tablename__ = 'body'
    id = Column(Integer, primary_key=True, autoincrement=True)
    body = Column(String)
    add_date = Column(DateTime)
    tags = relationship("BodyTags", back_populates="body")

class BodyTags(Base):
    __tablename__ = 'body_tags'
    id = Column(Integer, primary_key=True, autoincrement=True)
    body_id = Column(Integer, ForeignKey('body.id'))
    tag = Column(String)
    body = relationship("Body", back_populates="tags")

处理代码:

import pandas as pd
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 初始化数据库连接
engine = create_engine('postgresql://用户名:密码@主机:端口/数据库名')
Session = sessionmaker(bind=engine)
session = Session()

# 读取Excel数据
df = pd.read_excel('你的文件.xlsx')

# 遍历每一行数据
for _, row in df.iterrows():
    # 创建Body对象并提交,获取自动生成的ID
    new_body = Body(body=row['body'], add_date=row['add_date'])
    session.add(new_body)
    session.commit()
    
    # 处理三个标签,跳过空值
    for tag_col in ['tag1', 'tag2', 'tag3']:
        tag_value = row[tag_col]
        if pd.notna(tag_value):
            new_tag = BodyTags(body_id=new_body.id, tag=tag_value)
            session.add(new_tag)
    session.commit()

session.close()

方案二:批量插入后关联ID(适合大数据量)

如果数据量较大,逐行插入效率低,可以先批量插入Body表,再通过唯一字段关联获取ID,最后批量插入标签表。这种方式效率更高,但需要保证Body表有能匹配原数据的唯一标识(比如body+add_date的组合)。

处理代码:

import pandas as pd
from sqlalchemy import create_engine

# 初始化数据库连接
engine = create_engine('postgresql://用户名:密码@主机:端口/数据库名')

# 读取Excel数据
df = pd.read_excel('你的文件.xlsx')

# 1. 批量插入Body表
body_data = df[['body', 'add_date']].copy()
body_data.to_sql('body', engine, if_exists='append', index=False)

# 2. 查询已插入的Body数据,关联原DataFrame获取对应ID
# 假设body+add_date是唯一组合,能精准匹配
inserted_bodies = pd.read_sql("SELECT id, body, add_date FROM body", engine)
merged_df = pd.merge(df, inserted_bodies, on=['body', 'add_date'], how='left')

# 3. 构造标签数据并批量插入
tag_records = []
for _, row in merged_df.iterrows():
    body_id = row['id']
    # 遍历三个标签列,收集非空标签
    for col in ['tag1', 'tag2', 'tag3']:
        tag = row[col]
        if pd.notna(tag):
            tag_records.append({'body_id': body_id, 'tag': tag})

tag_df = pd.DataFrame(tag_records)
tag_df.to_sql('body_tags', engine, if_exists='append', index=False)

注意事项

  • 如果body+add_date不是唯一组合,可以在插入Body时额外保留原Excel的行号(比如新增row_num列),查询后通过行号关联ID。
  • 批量操作时建议加上事务控制,避免部分插入失败导致数据不一致,可以用with engine.begin() as conn:来管理事务。

内容的提问来源于stack exchange,提问作者uncrayon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 18:49:12