【问题标题】:How to insert unique data / handle duplicate data in a database如何在数据库中插入唯一数据/处理重复数据
【发布时间】:2016-01-21 10:44:22
【问题描述】:

假设它是一个模型定义:

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()

哪个更好?

【问题讨论】:

    标签: python orm error-handling flask sqlalchemy


    【解决方案1】:

    权限与宽恕

    在 Python 中,请求宽恕比请求许可 (EAFP) 更为惯用

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

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

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

    “前瞻版”(LBYL) 中的比赛条件

    无论您为确保没有重复项所做的任何检查都可能在您执行插入操作时过时。因此,很有可能在您的检查获得绿灯之后,您的程序的另一个实例(例如另一个 Flask 工作人员)会添加一行。

    这对您尤其有害,因为您的案例 B 不希望在检查清除后发生任何异常,这可能会完全停止程序的执行。所以案例 A 在这里轻松获胜。

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

    您的第二种方法总是发生在两个查询中(一个要检查,一个要添加),而第一个方法在重复的情况下抛出异常

    所以我会说你的案例 A 更好(只有在有重复时才处理异常的那个)

    不过不要撒网,抓住重点异常

    我看到的唯一挑剔是您应该使用except:(网太宽),而是使用插入重复行时抛出的特定异常。

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-24
        • 1970-01-01
        • 2018-09-30
        • 1970-01-01
        • 1970-01-01
        • 2016-08-24
        • 1970-01-01
        • 2015-01-06
        相关资源
        最近更新 更多