批量插入数据库唯一代码

时间:2015-04-20 11:44:45

标签: python django database

我需要创建许多独特的代码并将其插入数据库中。

当然我可以这样写:

codes = set()
while len(codes) < codes_size:
    c = generate_code()
    if len(Codes.objects.filter(code=c)) == 0:
        codes.add(Codes(c))
Codes.objects.bulk_create(codes)

但是当数据库已经包含很多代码时,它的工作速度很慢。

如果在每一代之后插入代码 - 它也非常慢。

现在最好的想法 - 在bulk_create之前不验证代码。如果bulk_create引发异常,则再次重新生成所有代码。例外情况非常罕见,但是当数据库更大时,异常会更频繁。

bulk_create不说哪个代码会引发异常。

1 个答案:

答案 0 :(得分:1)

我的理解是bulk_create()事务中执行它的操作,如果发生错误,它不会被提交。这意味着所有插入成功,或 none 成功。

例如,如果生成的代码与表中已有的代码重复,或者批处理中的另一个代码重复,则会引发IntegrityError异常且 none 的代码将被插入到数据库中。

就例外情况而言,您可能会获得django.db.utils.DatabaseError的子类,例如django.db.utils.IntegrityError。因为您不知道将引发哪个数据库错误,所以您应该捕获DatabaseError

我认为没有任何方法可以从异常中了解哪些代码导致了问题。

处理此问题的一种方法是预先生成所有代码,然后在transaction内使用filter()测试它们是否已经一次存在于表中并在那里插入它们没有重复:

from django.db import transaction

codes = set()
while len(codes) < codes_size:
    codes.add(generate_code())

with transaction.atomic():
    # check for any duplicate codes in table...
    dups = Codes.objects.filter(code__in=codes)
    if len(dups):
        print 'Duplicate code(s) generated: {}'.format(dup.code for dup in dups)
        # remove dups from codes, and generate additional codes to make up the shortfall.
        # Note that this might also result in duplicates....
    else:
        Codes.objects.bulk_create(Codes(code) for code in codes)

您仍然需要处理不是由于重复值而导致的数据库异常。为简单起见,我把它遗漏了。