Pau*_*eno 17 mysql auto-increment
我已经阅读了一些有关此内容的帖子但没有涉及此问题.
我猜它不可能,但无论如何我都会问.
我有一个超过50,000个寄存器的表.这是一个旧表,其中发生了各种插入/删除操作.
也就是说,大约300个寄存器中有一些"漏洞".即:...,1340,1341,1660,1661,1662,......
问题是.是否有一种简单/简单的方法可以使新的刀片填充这些"孔"?
保罗布埃诺
kar*_*grz 13
我同意@Aaron Digulla和@Shane N.这些差距毫无意义.如果他们DO意味着什么,这是一个有缺陷的数据库设计.期.
话虽这么说,如果你绝对需要填补这些漏洞,并且你至少运行MySQL 3.23,你可以利用TEMPORARY TABLE来创建一组新的ID.这里的想法是,您将按顺序将所有当前ID选择到临时表中:
CREATE TEMPORARY TABLE NewIDs
(
NewID INT UNSIGNED AUTO INCREMENT,
OldID INT UNSIGNED
)
INSERT INTO NewIDs (OldId)
SELECT
Id
FROM
OldTable
ORDER BY
Id ASC
Run Code Online (Sandbox Code Playgroud)
由于NewId列的AUTO INCREMENT属性,这将为您提供一个表格,将您的旧Id映射到本质上将是顺序的全新Id.
完成此操作后,您需要更新"OldTable"中对Id的任何其他引用以及它使用的任何外键.为此,您可能需要DROP任何外键约束,更新表中从OldId到NewId的任何引用,然后重新设置外键约束.
不过,我认为你不应该做任何的这个,只是知道,您的ID字段存在的引用记录的唯一目的,且应不具有任何特殊意义.
更新:添加更新ID的示例
例如:
假设您有以下两种表模式:
CREATE TABLE Parent
(
ParentId INT UNSIGNED AUTO INCREMENT,
Value INT UNSIGNED,
PRIMARY KEY (ParentId)
)
CREATE TABLE Child
(
ChildId INT UNSIGNED AUTO INCREMENT,
ParentId INT UNSIGNED,
PRIMARY KEY(ChildId),
FOREIGN KEY(ParentId) REFERENCES Parent(ParentId)
)
Run Code Online (Sandbox Code Playgroud)
现在,差距出现在您的父表中.
为了更新Parent和Child中的值,首先要创建一个包含映射的临时表:
CREATE TEMPORARY TABLE NewIDs
(
Id INT UNSIGNED AUTO INCREMENT,
ParentID INT UNSIGNED
)
INSERT INTO NewIDs (ParentId)
SELECT
ParentId
FROM
Parent
ORDER BY
ParentId ASC
Run Code Online (Sandbox Code Playgroud)
接下来,我们需要告诉MySQL忽略外键约束,以便我们可以正确地更新我们的值.我们将使用以下语法:
SET foreign_key_checks = 0;
Run Code Online (Sandbox Code Playgroud)
这会导致MySQL在更新值时忽略外键检查,但它仍然会强制使用正确的值类型(有关详细信息,请参阅MySQL参考).
接下来,我们需要使用新值更新Parent和Child表.我们将使用以下UPDATE语句:
UPDATE
Parent,
Child,
NewIds
SET
Parent.ParentId = NewIds.Id,
Child.ParentId = NewIds.Id
WHERE
Parent.ParentId = NewIds.ParentId AND
Child.ParentId = NewIds.ParentId
Run Code Online (Sandbox Code Playgroud)
我们现在已经将所有ParentId值正确更新为临时表中新的有序ID.完成后,我们可以重新设置外键检查以保持参照完整性:
SET foreign_key_checks = 1;
Run Code Online (Sandbox Code Playgroud)
最后,我们将删除临时表以清理资源:
DROP TABLE NewIds
Run Code Online (Sandbox Code Playgroud)
就是这样.
你需要这个功能的原因是什么?您的数据库应该没有间隙,如果您正在接近密钥的最大大小,只需将其设置为无符号或更改字段类型即可.
您通常不需要关心差距。如果您要到达ID的数据类型的末尾,则更改表以升级到下一个最大的int类型应该相对容易。
如果您绝对必须开始填补空白,请执行以下查询以返回最低的可用ID(希望不要太慢):
SELECT MIN(table0.id)+1 AS newid
FROM table AS table0
LEFT JOIN table AS table1 ON table1.id=table0.id+1
WHERE table1.id IS NULL
Run Code Online (Sandbox Code Playgroud)
(如果需要并发插入,请记住使用事务和/或捕获重复的键插入。)
归档时间: |
|
查看次数: |
16257 次 |
最近记录: |