在SQLAlChemy(声明性样式)中插入时处理重复的主键 [英] Dealing with duplicate primary keys on insert in SQLAlchemy (declarative style)

查看:115
本文介绍了在SQLAlChemy(声明性样式)中插入时处理重复的主键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序使用的是作用域会话和SQLALChemy的声明性样式。这是一个Web应用程序,很多数据库插入都是由任务调度程序Celery执行的。

通常,在决定插入对象时,我的代码可能会执行以下操作:

from schema import Session
from schema.models import Bike

pk = 123 # primary key
bike = Session.query(Bike).filter_by(bike_id=pk).first()
if not bike: # no bike in DB
    new_bike = Bike(pk, "shiny", "bike")
    Session.add(new_bike)
    Session.commit()
这里的问题是,因为很多工作都是由异步工作人员完成的,所以一个工作到一半(通过使用id=123插入Bike),而另一个工作在检查它是否存在的情况下是可能的。在这种情况下,第二个工作器将尝试插入具有相同主键的行,并且SQLAlChemy将引发一个IntegrityError

除了换出Session.commit()换成:

,我无论如何也找不到一个好的办法来处理这个问题
'''schema/__init__.py'''
from sqlalchemy.orm import scoped_session, sessionmaker
Session = scoped_session(sessionmaker())

def commit(ignore=False):
    try:
        Session.commit()
    except IntegrityError as e:
        reason = e.message
        logger.warning(reason)

        if not ignore:
            raise e

        if "Duplicate entry" in reason:
            logger.info("%s already in table." % e.params[0])
            Session.rollback()

然后在我拥有的任何位置Session.commit我现在都有schema.commit(ignore=True),我不介意该行不会再次插入。

在我看来,由于字符串检查,这似乎非常脆弱。就像FYI一样,当引发IntegrityError时,它看起来如下所示:

(IntegrityError) (1062, "Duplicate entry '123' for key 'PRIMARY'")

当然,我插入的主键类似于Duplicate entry is a cool thing,那么我想我可能会错过IntegrityError,实际上并不是因为重复的主键。

有没有更好的方法来维护我正在使用的干净的SQLAlChemy方法(而不是开始写出字符串中的语句等)。.)

DB是MySQL(尽管对于单元测试,我喜欢使用SQLite,并且不想用任何新方法阻碍这种能力)。

干杯!

推荐答案

如果使用session.merge(bike)而不是session.add(bike),则不会生成主键错误。将根据需要检索和更新或创建bike

这篇关于在SQLAlChemy(声明性样式)中插入时处理重复的主键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆