1

我有正在处理的记录,部分过程正在消除重复记录。有了这个,我已经使用 SQLAlchemy 在我的表上创建了 UniqueContraints,除了在 for 循环中运行的 save 函数之外,我有以下捕获:

代码1

for record in millionsofrecords:
    try:
        #code to save 
        session.flush()
    except IntegrityError:
        logger("live_loader", LOGLEVEL.warning, "Duplicate Entry")
    except:
        logger("live_loader", LOGLEVEL.critical, "\n%s" %(sys.exc_info()[1]))
        raise       

有了上述内容,我可以捕获错误,但是 SQLAlchemy 在下一个循环中声明:sqlalchemy.exc.InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback().. 所以我更改为以下内容:

代码2

for record in millionsofrecords:
    try:
        #code to save 
        session.flush()
    except IntegrityError:
        logger("live_loader", LOGLEVEL.warning, "Duplicate Entry")
        session.rollback()
    except:
        logger("live_loader", LOGLEVEL.critical, ":%s" %(sys.exc_info()[1]))
        raise   

我将函数更改为包含 session.rollback 但随后插入重复检测的任何记录都将被丢弃。

questions:

  1. 当检测到重复时,我想跳过那个“1”记录,但插入其余不重复的记录。当我添加session.rollback如上所示的内容时code2,甚至之前刷新的所有记录都被“丢弃”。我只想丢弃重复的记录,但允许保存所有其余的记录。

  2. 考虑到我将处理许多记录,这是一个更好的设计。在数据库上做一个快速的选择语句来检测重复,或者做现在正在做的事情,让数据库唯一键为我工作,同时我捕获重复异常并继续前进?

4

1 回答 1

1

您正在做的事情(特别是如果您有很多记录)正在执行许多查询,这是非常低效的。因此,构建一个查询来检测重复是一个更好的主意。对于将来,您仍然应该保留唯一约束以避免进一步的冲突,但是对于转换(或您在那里所做的任何事情),进行这样的查询要高效得多。您甚至可以将结果转换为字典,因为如果您需要通过键查找内容,这通常会更有效。

此外,关于速度,如果您需要执行类似的操作,请使用 aset而不是 a ,因为它更有效。listvalue in duplicates

现在,如果您想保留旧方式,请使用savepoints。这里的想法是你说“好吧,到目前为止我很好,让我们保留这个,所以当我回滚时,只有我不确定的最后一点”。你的例子有点短,给你一个例子,但通常,在向数据库添加东西之前,你先做一个begin_nested然后提交或回滚。

于 2013-09-08T22:12:41.300 回答