本文介绍了在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(声明性样式)中插入时处理重复的主键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!