根据 MySQL / MariaDB 中的新序列更新主键值

update primary key values based on a new sequence in MySQL / MariaDB

提问人:Matías Cánepa 提问时间:8/9/2021 更新时间:8/11/2021 访问量:556

问:

考虑一个以列为主键的表,并具有自动递增my_tableid_my_table

CREATE TABLE `my_table` (
  `id_my_table` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `some_name` VARCHAR(50) NOT NULL,
  PRIMARY KEY (`id_my_table`)
) ENGINE=InnoDB;

该主键由其他一些表引用。

我有一些记录,为了这个例子,假设我有五个记录具有以下值:1、2、3、4 和 5。由于客户端的请求涉及从旧数据集中获取特定序列,因此我更新了主键的值以匹配该序列。id_my_table

这是我所做的:

ALTER TABLE `my_table` ADD COLUMN `my_old_id` INT UNSIGNED NULL AFTER `some_name`;

UPDATE `my_table` set `my_old_id` = `id_my_table`;

SET FOREIGN_KEY_CHECKS=0;

-- +100 so no duplicate error...
UPDATE `my_table` set `id_my_table` = `id_my_table` + 100;

UPDATE `my_table` set `id_my_table` = 25 where `id_my_table` = 1;
UPDATE `my_table` set `id_my_table` = 37 where `id_my_table` = 2;
UPDATE `my_table` set `id_my_table` = 58 where `id_my_table` = 3;
UPDATE `my_table` set `id_my_table` = 72 where `id_my_table` = 4;
UPDATE `my_table` set `id_my_table` = 96 where `id_my_table` = 5;

ALTER TABLE `my_table` AUTO_INCREMENT = 97;

UPDATE another_table at
INNER JOIN my_table mt on mt.my_old_id = at.reference_to_id_my_table
SET at.reference_to_id_my_table = mt.id_my_table;

SET FOREIGN_KEY_CHECKS=1;

现在一切都按预期工作,新记录具有正确的顺序(基于旧记录),但是......

我可以正常继续吗?还是我搞砸了一些内部索引,我没有发现潜在的问题?

mysql mariadb 序列 主键

评论

0赞 nbk 8/9/2021
当您操作索引时,索引会自动更新,但您可以检查索引的运行状况和/或重新生成索引。
0赞 Matías Cánepa 8/9/2021
如何检查健康状况? ?CHECK TABLE my_table
0赞 nbk 8/9/2021
SHOW EXTENDED INDEX from table1;
0赞 Matías Cánepa 8/10/2021
@nbk如果有什么问题,那么我应该在列中看到一些东西吗?Index_comment
0赞 Akina 8/16/2021
ON UPDATE CASCADE在 FK 定义中也会做同样的事情,但要容易一千倍......

答:

1赞 Rick James 8/11/2021 #1

简短的回答:看起来不错。

长答案:

测试这一点的“正确”方法是将所有相关表复制到另一台服务器(或在同一台服务器上,但在不同的数据库中)。然后执行一些操作,例如通过外键获取或添加新行(这将得到 id=97)。

还有一件事要做:把 .此单个事务将确保完成所有更新或未完成。START TRANSACTIONCOMMITUPDATEs

顺便说一句,我认为您的代码没有任何问题。(我假设将针对引用的每个表完成 Join 的更新。(如果您已经运行了所有更新,请不要担心事务。把它看作是“下次”的提示。my_table

至于如何运作,我看不出任何未来的陷阱。新 ID 将为 97 及以上;差距中的数字将永远消失。AUTO_INCREMENT

请注意,它是 + ,因此在所有(?)情况下,它将丢失auto_inc id。REPLACEDELETEINSERT

您是否必须编写 5 个更新?使用映射构建表,然后将其应用于所有相关表可能更容易。在主表的情况下,只有当存在重复 ID 的风险时,您才可能需要一些技巧(例如 +100)才是必要的。

考虑稍后再做。DROP COLUMN

评论

0赞 Matías Cánepa 8/11/2021
感谢您的详细回答。这五个更新只是为了说明,我实际上有一个带有连接的更新(序列来自哪里)。我将按照您的建议实现交易