如何在数据库中插入唯一数据/处理重复数据

时间:2016-01-21 10:44:22

标签: python orm error-handling flask sqlalchemy

假设它是模型定义:

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    account = Column(String(255), unique=True, index=True)
    password = Column(String(128))
    created_at = Column(DateTime, default=datetime.datetime.utcnow)
    updated_at = Column(DateTime, onupdate=datetime.datetime.utcnow,
                        default=datetime.datetime.utcnow)

假设我已在数据库中插入Tom但您再次插入它。你更喜欢哪种处理方法?

<案例A

让它发生错误,然后处理错误。

try:
    user = User(account='Tom', ...)
    session.add(user)
    session.commit()
except:
    # do something
<案例B

搜索用户是否存在。如果它不存在,它将创建。

user = session.query(User).filter(User.account == 'Tom').one()
if user:
    # do something
user = User(account='Tom', ...)
session.add(user)
session.commit()

哪个更好?

2 个答案:

答案 0 :(得分:3)

权限与宽恕

在Python中,要求宽恕而非许可(EAFP)更为惯用

  

<强> EAFP :   比许可更容易请求宽恕。这种常见的Python编码风格假设存在有效的键或属性,并且如果假设被证明是错误则捕获异常。这种干净和快速的风格的特点是存在许多try和except语句。该技术与许多其他语言(如C。

)共有的LBYL风格形成对比

来源:https://docs.python.org/3.4/glossary.html

在这方面,你的案例A方法更好。

&#34;竞争条件在您跳跃版本之前看看&#34; (LBYL

无论您做什么检查以确保没有重复,您可以在插入时间过时。因此,在您的检查发出绿灯后,您的程序的另一个实例(例如另一个Flask工作人员)会添加一行,这很可能。

这对您来说尤其具有破坏性,因为您的案例B不是,如果该检查清除,则不会发生任何异常,这可能会完全阻止程序的执行。案例A很容易在这里胜出。

性能:两个查询与一个查询+一个可能的异常

此外,您的第二个方法始终发生在两个查询中(一个用于检查,一个用于添加),而第一个方法在重复的情况下抛出异常

所以我说你的案例A更好(只有在有重复时处理例外的案例)

虽然没有投出一个广泛的网,但是抓住一个集中的例外

我看到的唯一的挑剔是你应该 NOT 使用except:(太宽的网),但是使用一个特殊的异常,当你插入一个重复的行时会抛出。

假设在这种情况下抛出的是IntegrityError,我们应该

try:
     # Insert a potentially duplicate row
except IntegrityError:
     # Deal with the case

答案 1 :(得分:1)

在Web应用程序开发中,您需要随着时间的推移增强应用程序,减少数据库查询是您在一段时间内需要的增强功能之一。因此案例A比案例B更好。因为如果找不到用户,它只运行一个查询(1个查询来更新数据)如果找不到使用(1个查询要创建)。

我还想推荐Daniel Roy Greenfeld和Audrey Roy Greenfeld以及Peter Baumgartner和Yann Malet撰写的关于Django Web应用程序开发的杰出书籍Two Scoops of Django