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

在MySQL中使用SQLAlchemy无法处理on_conflict_do_nothing问题

解决SQLAlchemy批量插入MySQL时跳过冲突数据的问题

当前代码使用ORM的db.add_all()方法批量插入数据,遇到唯一键冲突时会直接抛出异常,无法跳过冲突行。要实现跳过冲突数据,需要利用MySQL的冲突处理语法,结合SQLAlchemy核心层的insert语句来实现,以下是两种可行方案:

方案一:使用INSERT IGNORE跳过冲突行

这种方式会忽略触发唯一键约束的行,继续插入其余数据。

修改后的代码:

from sqlalchemy.orm import Session
from sqlalchemy import insert

from app.config import config
from app.datastores.mysql.db import get_db
from app.datastores.mysql.models import models, schemas

async def adding_cronjob_alerts(
    alert: schemas.CreateAlert, generate_uuid, db: Session = Depends(get_db)
):
    logger.debug(f"[{generate_uuid}] - Customer Alert Doesn't Exist In DB => Storing")
    # 构造批量插入的字典数据(无需创建ORM模型实例)
    alerts_data = [item.dict() for item in alert]
    logger.debug(f"[{generate_uuid}] - Adding Customer Alerts Record To DB")
    # 构造带IGNORE前缀的insert语句
    insert_stmt = insert(models.ReaqtaAlerts).prefix_with('IGNORE').values(alerts_data)
    # 执行插入
    db.execute(insert_stmt)
    logger.debug(f"[{generate_uuid}] - Alerts Added Successfully")
    logger.debug(f"[{generate_uuid}] - Committing DB Session To MySQL Database")
    db.commit()
    logger.debug(f"[{generate_uuid}] - {CLOSING_DB_SESSION_STRING}")
    db.close()

方案二:使用ON DUPLICATE KEY UPDATE(可选更新或无操作)

如果需要在冲突时更新字段,或者仅需跳过冲突(通过设置无意义的更新操作),可以使用该方式:

# 构造insert语句,冲突时可选择更新字段或无操作
insert_stmt = insert(models.ReaqtaAlerts).values(alerts_data).on_duplicate_key_update(
    # 示例1:更新updated_at字段为当前时间
    # updated_at=func.now(),
    # 示例2:无操作(仅跳过冲突)
    id=models.ReaqtaAlerts.id
)
db.execute(insert_stmt)

注意事项

  • 确保ReaqtaAlerts模型定义了唯一键约束(主键、unique=True的字段),否则MySQL无法检测到冲突。
  • 使用SQLAlchemy核心层的insert语句比ORM的add_all()性能更高,避免了创建大量模型实例的开销。
  • 该方案适用于SQLAlchemy 1.4及以上版本,以及MySQL 5.1+版本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 16:50:44