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

如何在Python+SQLAlchemy+SQLite环境下结合ON CONFLICT DO NOTHING实现批量插入?

如何在Python+SQLAlchemy+SQLite环境下结合ON CONFLICT DO NOTHING实现批量插入?

看起来你是要把批量金融时序数据导入SQLite数据库,同时要避免重复插入相同时间戳的记录对吧?我来给你一步步讲怎么用SQLAlchemy实现这个需求,结合ON CONFLICT DO NOTHING来处理冲突:

第一步:完善你的数据库模型

首先先把你没写完的模型补全,要实现冲突处理,我们需要把Timestamp设为主键(或者唯一索引),这样SQLite才能识别重复冲突:

import datetime
from typing import List
from sqlalchemy import String, Integer, Float
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped, mapped_column

class Base(DeclarativeBase):
    pass

class PriceData(Base):
    __tablename__ = "price_data"
    
    # 把Timestamp设为主键,确保唯一性
    timestamp: Mapped[int] = mapped_column(Integer, primary_key=True)
    open: Mapped[float] = mapped_column(Float)
    high: Mapped[float] = mapped_column(Float)
    low: Mapped[float] = mapped_column(Float)
    close: Mapped[float] = mapped_column(Float)

然后别忘了先创建数据库表:

from sqlalchemy import create_engine

engine = create_engine("sqlite:///financial_market.db")
# 创建所有表
Base.metadata.create_all(engine)

第二步:读取CSV数据

假设你用pandas来处理CSV(金融数据处理的常用工具),需要把原本作为索引的Timestamp转成普通列,方便后续插入:

import pandas as pd

# 读取CSV,指定Timestamp为索引
df = pd.read_csv("your_financial_data.csv", index_col="Timestamp")
# 把索引转为普通列
df.reset_index(inplace=True)
# 转成字典列表,方便SQLAlchemy处理
data_records = df.to_dict("records")

第三步:批量插入+冲突忽略(核心步骤)

这里推荐用SQLAlchemy Core层的插入语句,因为它更高效,而且原生支持ON CONFLICT DO NOTHING,非常适合大数据量的批量导入:

from sqlalchemy import insert

with engine.connect() as conn:
    # 构建插入语句,指定当timestamp主键冲突时,不做任何操作
    insert_stmt = insert(PriceData).values(data_records).on_conflict_do_nothing(
        index_elements=["timestamp"]  # 指定用来判断冲突的索引列(这里是主键)
    )
    # 执行插入
    conn.execute(insert_stmt)
    # 提交事务
    conn.commit()

补充:如果想用ORM会话实现

如果你更习惯用ORM的Session,也可以用同样的插入语句,只是通过会话执行:

from sqlalchemy.orm import Session

with Session(engine) as session:
    insert_stmt = insert(PriceData).values(data_records).on_conflict_do_nothing(index_elements=["timestamp"])
    session.execute(insert_stmt)
    session.commit()

关键说明

  • on_conflict_do_nothing会告诉SQLite:当插入的记录和已有记录在指定的索引列(这里是timestamp主键)上重复时,直接跳过这条记录,不会抛出错误,也不会修改已有数据。
  • 这种方法比先查询所有已有时间戳再过滤数据要高效得多,尤其是数据量很大的时候,因为所有逻辑都在数据库层面完成,减少了Python和数据库之间的交互。

备注:内容来源于stack exchange,提问作者kamran nasirizad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 11:14:28