我如何知道某个模型的下一个免费主键?
6 回答
即使您可以查询下一个可用的主键值,它也无济于事。除非您锁定表,否则您不能在其他数据库客户端获取该值进行插入之前使用该值。
相反,您应该只插入您的行,然后您可以查询当前会话期间生成的最新键值。每个支持自动生成主键的数据库都提供了一种方法来检索会话期间插入的最新键。
“在您的会话期间”部分很重要,因为它使您的会话免受其他客户端同时进行的任何插入的影响。它们可以生成键值,您的会话将继续报告它最近插入的相同值。
@Stuart Childs假设MySQL 生成下一个 ID,MAX(column_name)+1
但这是不正确的。假设您插入一行并生成一个 ID 值。但是您回滚此插入,或随后回滚该DELETE
行。下次插入时,MySQL 会生成一个全新的 ID 值。因此,无论表中当前存储了哪些行, ID 值都比任何客户端生成的最后一个 ID 值大一。
同样,如果您插入但不立即提交。在您提交之前,其他一些客户端会执行插入操作。您的会话和其他客户的会话都将生成自己的唯一 ID 值。自动生成的主键操作不考虑事务隔离,以确保唯一性。
自动生成的主键值不会重复使用或分配给多个会话,即使您尚未提交插入、回滚插入或删除行也是如此。
- 使用 Django 和 Mysql
next_id = Table.objects.filter(id__gt = current_id)[0].id
next_id = User.objects.order_by('-id').first().id + 1
如果不存在,可能需要处理。
或使用最大查询:
from django.db.models import Max
users = User.objects.all()
#might be possible model has no records so make sure to handle None
next_id = users.aggregate(Max('id'))['id__max'] + 1 if users else 1
我认为您必须执行一些自定义 SQL。您需要的 SQL 将是特定于数据库的。据我所知,在 MySQL 中没有可靠的方法来做到这一点。您可以获得最后一个插入 ID,但它是特定于会话的(即,您可以获得您在数据库会话中插入的最后一条记录的 ID,但不能获得可能在您之后发生的另一个会话的最后一个 ID)。 但是(如果我错了,有人纠正我),MySQL 使用 MAX(column_name) + 1 生成下一个 ID,所以你可以这样做。
PostgreSQL 通过它的序列操作函数使它变得容易得多。
编辑:
原来我正在考虑使用 MAX(column_name)+1 生成AUTO_INCREMENT
的多列键中的列。但是,重点仍然是在下一个 ID由插入生成之前无法检索它,这是原始问题。
我有同样的问题,因为我正在复制一个元素,我想将它的 pk 更改为一个新的以便能够插入它。
我的解决方案如下:
import copy
objectCopy=copy.copy(object)
objectCopy.pk=None
objectCopy.save()
我的意思是,如果save()
为你做,你为什么要手动做呢?
这个片段肯定会帮助你。