删除所有实例后,Django 模型实例主键不会重置为 1
Django model instances primary keys do not reset to 1 after all instances are deleted
我一直在开发我的 Django 网络应用程序的离线版本,并且经常删除某个 ModelX 的模型实例。
我已从管理页面完成此操作,没有遇到任何问题。该模型只有两个字段:名称和顺序,与其他模型没有其他关系。
新实例被赋予下一个可用的 pk,这是有道理的,当我删除所有实例后,添加一个新实例会产生 pk=1,这符合我的预期。
将代码在线移动到我的实际数据库中,我发现情况并非如此。我需要更改模型实例,所以我将它们全部删除,但令我惊讶的是,主键一直在递增而没有重置回 1。
使用 Django 进入数据库 API 我已经检查过,旧实例已经消失,但即使添加新实例也会产生一个主键,该主键从上次删除的实例停止的地方开始,而不是 1 .
想知道是否有人知道这里可能是什么问题。
您实际上是从数据库中删除了它们还是使用 Django 删除了它们? Django 不会仅通过从中删除行来为您的 table 更改 AUTO_INCREMENT
,因此如果您想重置主键,您可能必须进入您的数据库并:
ALTER TABLE <my-table> AUTO_INCREMENT = 1;
(假设您使用的是 MySQL 或类似的)。
我不认为这是一个问题。这是许多数据库系统的默认行为。基本上,table 的自动递增计数器是持久的,删除条目不会影响计数器。主键的实际值不会影响性能或其他任何东西,它只具有美学价值(如果达到 20 亿的限制,您很可能会有其他问题需要担心)。
如果你真的想重置计数器,你可以删除并重新创建 table:
python manage.py sqlclear <app_name> > python manage.py dbshell
或者,如果您需要保留应用中其他 table 的数据,您可以手动重置计数器:
python manage.py dbshell
mysql> ALTER TABLE <table_name> AUTO_INCREMENT = 1;
您在离线和在线应用程序中看到不同行为的最可能原因是自动增量值只存储在内存中,而不是磁盘上。每次重新启动数据库服务器时,它都会重新计算为 MAX(<column>) + 1
。如果 table 为空,它将在重新启动时完全重置。这对于您的离线环境可能很常见,而对于您的在线环境则接近 none。
没问题,这就是数据库的工作方式。 Django 与生成 id 没有任何关系,它只是告诉数据库插入一行并从数据库响应中获取 id。每个 table 的 id 从 1 开始,并在每次插入行时递增。删除行不会导致 id 返回。你通常不应该关心这一点,你只需要知道每一行都有一个唯一的 id。
您当然可以使用数据库命令更改为您的 table 生成 ID 的计数器,这取决于您使用的特定数据库系统。
正如其他人所说,这完全是数据库的责任。
但是您应该意识到这是理想的行为。 ID 唯一标识数据库中的实体。因此,它应该只引用一行。如果该行随后被删除,那么您没有理由希望新行重新使用该 ID:如果您这样做,您会在曾经拥有该 ID 的现已删除的实体与现在删除的实体之间造成混淆新创建的重复使用它。这样做没有意义,您不应该这样做。
我不确定这是什么时候添加的,但是下面的管理命令会删除所有表中的所有数据,并将自动递增计数器重置为 1。
./manage.py sqlflush | psql DATABASE_NAME
如果您使用的是 SQLite,则可以使用以下 shell 命令重置主键:
DELETE FROM your_table;
DELETE FROM SQLite_sequence WHERE name='your_table';
'POSTGRES' 数据库的另一个解决方案来自 UI。
Select 你的 table 并寻找 'sequences' 下拉菜单和 select 设置并以此方式调整序列。
示例:
我一直在开发我的 Django 网络应用程序的离线版本,并且经常删除某个 ModelX 的模型实例。
我已从管理页面完成此操作,没有遇到任何问题。该模型只有两个字段:名称和顺序,与其他模型没有其他关系。
新实例被赋予下一个可用的 pk,这是有道理的,当我删除所有实例后,添加一个新实例会产生 pk=1,这符合我的预期。
将代码在线移动到我的实际数据库中,我发现情况并非如此。我需要更改模型实例,所以我将它们全部删除,但令我惊讶的是,主键一直在递增而没有重置回 1。
使用 Django 进入数据库 API 我已经检查过,旧实例已经消失,但即使添加新实例也会产生一个主键,该主键从上次删除的实例停止的地方开始,而不是 1 .
想知道是否有人知道这里可能是什么问题。
您实际上是从数据库中删除了它们还是使用 Django 删除了它们? Django 不会仅通过从中删除行来为您的 table 更改 AUTO_INCREMENT
,因此如果您想重置主键,您可能必须进入您的数据库并:
ALTER TABLE <my-table> AUTO_INCREMENT = 1;
(假设您使用的是 MySQL 或类似的)。
我不认为这是一个问题。这是许多数据库系统的默认行为。基本上,table 的自动递增计数器是持久的,删除条目不会影响计数器。主键的实际值不会影响性能或其他任何东西,它只具有美学价值(如果达到 20 亿的限制,您很可能会有其他问题需要担心)。
如果你真的想重置计数器,你可以删除并重新创建 table:
python manage.py sqlclear <app_name> > python manage.py dbshell
或者,如果您需要保留应用中其他 table 的数据,您可以手动重置计数器:
python manage.py dbshell
mysql> ALTER TABLE <table_name> AUTO_INCREMENT = 1;
您在离线和在线应用程序中看到不同行为的最可能原因是自动增量值只存储在内存中,而不是磁盘上。每次重新启动数据库服务器时,它都会重新计算为 MAX(<column>) + 1
。如果 table 为空,它将在重新启动时完全重置。这对于您的离线环境可能很常见,而对于您的在线环境则接近 none。
没问题,这就是数据库的工作方式。 Django 与生成 id 没有任何关系,它只是告诉数据库插入一行并从数据库响应中获取 id。每个 table 的 id 从 1 开始,并在每次插入行时递增。删除行不会导致 id 返回。你通常不应该关心这一点,你只需要知道每一行都有一个唯一的 id。
您当然可以使用数据库命令更改为您的 table 生成 ID 的计数器,这取决于您使用的特定数据库系统。
正如其他人所说,这完全是数据库的责任。
但是您应该意识到这是理想的行为。 ID 唯一标识数据库中的实体。因此,它应该只引用一行。如果该行随后被删除,那么您没有理由希望新行重新使用该 ID:如果您这样做,您会在曾经拥有该 ID 的现已删除的实体与现在删除的实体之间造成混淆新创建的重复使用它。这样做没有意义,您不应该这样做。
我不确定这是什么时候添加的,但是下面的管理命令会删除所有表中的所有数据,并将自动递增计数器重置为 1。
./manage.py sqlflush | psql DATABASE_NAME
如果您使用的是 SQLite,则可以使用以下 shell 命令重置主键:
DELETE FROM your_table; DELETE FROM SQLite_sequence WHERE name='your_table';
'POSTGRES' 数据库的另一个解决方案来自 UI。 Select 你的 table 并寻找 'sequences' 下拉菜单和 select 设置并以此方式调整序列。
示例: