刚刚使用数据库,最近进行了一些测试,检查了设置的完整性。
结果,添加了许多测试条目,然后将其删除。但是,当添加新条目时,ID 编号值会在添加条目之后继续。
我想要什么:ID 从添加其他行之前停止的位置增加一:4203、4204、4205、4206 等。
发生了什么:ID 从附加行 ID 之后增加一:4203、4204、6207、6208 6209 等。
不知道在哪里解决这个问题......无论是在 phpmyadmin 还是在 PHP 代码中。任何帮助,将不胜感激。谢谢!
刚刚使用数据库,最近进行了一些测试,检查了设置的完整性。
结果,添加了许多测试条目,然后将其删除。但是,当添加新条目时,ID 编号值会在添加条目之后继续。
我想要什么:ID 从添加其他行之前停止的位置增加一:4203、4204、4205、4206 等。
发生了什么:ID 从附加行 ID 之后增加一:4203、4204、6207、6208 6209 等。
不知道在哪里解决这个问题......无论是在 phpmyadmin 还是在 PHP 代码中。任何帮助,将不胜感激。谢谢!
我以前遇到过这个问题,我用 phpMyAdmin 轻松解决了这个问题。选择数据库,选择表,打开操作选项卡,在表选项中将 AUTO_INCREMENT 设置为 1,然后单击 GO。这将强制 mysql 查找最后一个自动递增的值,然后直接将其设置为该值。我手动执行此操作,我知道当跳过一行时,它不是来自测试而是删除,因为当我测试和删除行时,我修复了 AI 值。
我认为没有办法使用自动递增的 ID 密钥来做到这一点。您可能可以通过将 ID 分配给 (select max(id) + 1 from the_table)
您可以删除主键然后重新创建它,但这会重新分配所有现有的主键,因此可能会导致关系出现问题(尽管如果您的主键中没有任何间隙,您可能会侥幸逃脱)。
但是,我会说您应该接受(并且您的应用程序应该反映)丢失 ID 的可能性。例如,在 Web 应用程序中,如果有人链接到丢失的 ID,您会希望 404 返回而不是不同的记录。
不需要“重置” id 值;我同意关于这个问题的其他评论。
您使用 AUTO_INCREMENT 观察到的行为是设计使然;它在 MySQL 文档中进行了描述。
话虽如此,我将描述一种方法,您可以使用它来“向下”更改这些行的 id 值,并使它们全部连续:
作为“垫脚石”的第一步,我们将创建一个查询来获取id
我们需要更改的值的列表,以及id
我们要将其更改为的提议的新值。此查询使用 MySQL 用户变量。
假设 4203 是id
您要保持原样的值,并且您希望将下一个较高的id
值重置为 4204,将下一个较高id
的值重置为 4205,等等。
SELECT s.id
, @i := @i + 1 AS new_id
FROM mytable s
JOIN (SELECT @i := 4203) i
WHERE s.id > 4203
ORDER BY s.id
(注意:常量值4203
在上面的查询中出现了两次。)
一旦我们对该查询的工作感到满意,并返回旧的和新的 id 值,我们就可以在多表 UPDATE 语句中将此查询用作内联视图(MySQL 将其称为派生表)。我们只需将该查询包装在一组括号中,并为其分配一个别名,这样我们就可以像普通表一样引用它。(在内联视图中,MySQL 实际上将查询返回的结果集具体化为 MyISAM 表,这可能解释了为什么 MySQL 将其称为“派生表”。)
下面是一个引用派生表的示例 UPDATE 语句:
UPDATE ( SELECT s.id
, @i := @i + 1 AS new_id
FROM mytable s
JOIN (SELECT @i := 4203) i
WHERE s.id > 4203
ORDER BY s.id
) n
JOIN mytable t
ON t.id = n.id
SET t.id = n.new_id
ORDER BY t.id
请注意,内联视图中的旧 id 值与现有表(ON
子句)中的 id 值匹配,并且内联视图生成的“new_id”值分配给 id 列(SET
子句)。
一旦分配了 id 值,我们就可以重置表上的 AUTO_INCREMENT 值:
ALTER TABLE mytable AUTO_INCREMENT = 1;
注意:这只是一个示例,并提供了一个警告,即不需要重新分配 id 值。理想情况下,主键值应该是 IMMUTABLE 即它们一旦被分配就不应改变。