我有正在处理的记录,部分过程正在消除重复。有了这个,我使用SQLAlchemy在我的表上创建了UniqueContraints,除了在for循环中运行的save函数之外,我有以下的catch:
CODE1
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,但是任何插入pior的记录都会被丢弃。
questions:
当检测到重复时,我想跳过那个“1”记录,但插入其余不重复的记录。当我添加上面session.rollback
中显示的code2
时,之前已经刷过的所有记录都被“丢弃”。我只想丢弃重复记录,但允许保存所有其余记录。
鉴于我将处理许多记录,这是一个更好的设计。在数据库上执行快速选择语句以检测重复或现在正在执行的操作并使数据库唯一键对我起作用,同时捕获重复异常并继续前进?
答案 0 :(得分:1)
您正在做什么(特别是如果您有许多记录)正在执行许多查询,这是非常低效的。因此,构建查询以检测重复项是更好的主意。对于未来,您仍应保留唯一约束以避免进一步的冲突,但对于转换(或者您在那里做的任何事情),进行此类查询会更有效。您甚至可以将结果转换为字典,因为如果您需要通过密钥查找内容,这通常会更有效。
此外,关于速度,如果您需要执行set
之类的操作,请使用list
而不是value in duplicates
,因为它更有效。
现在,如果您想保持原来的方式,请使用savepoints。这里的想法是你说“好吧到目前为止我很好,让我们保持这个,所以当我回滚时,只有我还不确定的最后一点”。您的示例有点简短,只是为了给您一个示例,但通常,在向数据库添加内容之前,您创建begin_nested
,然后提交或回滚。