Php MySQL修复两个表中的自动增量间隙
我有两张这样的桌子Php MySQL修复两个表中的自动增量间隙,php,mysql,database,auto-increment,Php,Mysql,Database,Auto Increment,我有两张这样的桌子 id_image foo bar 1 3 5 2 8 1 3 17 88 7 14 23 8 12 9 id_image bar foo 1 2 3 1 5 6 2 18 11 2 10 12 3
id_image foo bar
1 3 5
2 8 1
3 17 88
7 14 23
8 12 9
id_image bar foo
1 2 3
1 5 6
2 18 11
2 10 12
3 8 21
3 17 81
7 29 50
7 1 14
8 10 26
8 27 34
第一个表中自动递增的id\u图像中存在间隙。在第二个表中,id\u图像
指的是第一个表中的id\u图像
,每个id中有两个
注意:此表是理论表。我不知道差距到底在哪里,也不知道是否存在多个差距。我只知道第一个值是1
,最后一个值高于行总数
现在,我想弥补这个差距
在你说差距无关紧要之前,让我告诉你,如果差距真的存在,那就是糟糕的数据库设计;我同意你的看法
然而,我要处理的是一个(无可救药的后端向后)第三方开源系统,我需要将大量没有交叉引用ID的现有数据导入到多个表中。我唯一能确保相同的数据在整个系统的每个表中都获得匹配ID的方法是按顺序输入,这意味着我不能有间隙
所以我现在需要做的是
修复第一个表中id\u image
列中的间隙,以便最后一个值与行计数匹配
编辑第二个表中的id\u image
列,使其值对应于间隙修正之前的同一行
我将如何开始这样做?我知道这可能超出了MySQL查询语言的功能范围,所以PHP答案也是可以接受的。谢谢!:)
FK将相应地自动更新第二个表的ID
我一点也不确定,但在一些较旧版本的mysql中,更新子查询中引用的表可能会崩溃。如果是这样,只需创建第二个表并填充(插入),然后删除旧表并重命名新表。
创建一个与第一个类似的表,在Id_图像上没有标识,并创建一个名为rownumber的额外int列
使用伪行数技巧填充它,例如
Insert into NewTable
Select id_image,foo,bar,@RowNumber := @RowNumber + 1 order by id_image.
如果您有第二个表的外键,请删除它,这是一个带有联接的简单更新。删除旧表1,重命名新表,添加标识并重新设定种子,如果有外键,则将其放回原处
你意识到你必须继续做这些废话吗
如果你有层叠的更新,可能有一个有趣的方法一次完成所有这些,但是要注意执行计划。行数技巧只有在按Id_图像顺序进行操作时才有效。如果Mysql决定有一种更有效的查询方法……这里的基本思想是首先找到所有的间隙,以确定需要减少多少id。然后,必须迭代两个表并应用减少量。(您需要添加:主机、数据库、用户、传递和实际表名)
试试看{
$pdo=newpdo('mysql:host=host;dbname=DB','user','pass');
$pdo->beginTransaction();
//遍历第一个表中的所有id
$stmt=$pdo->exec('SELECT image_id FROM TableOne ORDER BY image_id ASC');
$stmt->bindColumn('image_id',$id);
if(!$stmt->fetch(PDO::fetch_-BOUND)){
抛出异常(“表中没有行”);
}
$lastId=$id;
$gaps=array();
//找出所有的差距
while($stmt->fetch(PDO::fetch_-BOUND)){
如果($id!=($lastId+1)){
$gaps[]=$id;
}
$lastId=$id;
}
如果(!isset($gaps[0])){
抛出新异常(“未找到间隙”);
}
//对于每个间隙,通过减法更新从最后一个间隙到该间隙的范围
//id中已存在的间隙数
$lastGap=$gaps[0];
对于($i=1;$iprepare('updatetableone SET image\u id=image\u id-:i其中image\u id介于:lastpag和:gap之间');
$stmt->execute(数组)(
“:i”=>$i,
“:lastGap”=>$lastGap,
':gap'=>$gaps[$i]
));
$stmt=$pdo->prepare('updatetabletwo SET image\u id=image\u id-:i其中image\u id介于:lastGap和:gap之间');
$stmt->execute(数组)(
“:i”=>$i,
“:lastGap”=>$lastGap,
':gap'=>$gaps[$i]
));
$lastGap=$gaps[$i];
}
//最后,修复最后找到的间隙和表末尾之间的间隙
$stmt=$pdo->prepare('updatetableone SET image\u id=image\u id-:i其中image\u id介于:lastpag和:gap之间');
$stmt->execute(数组)(
“:i”=>$i,
“:lastGap”=>$lastGap,
':gap'=>$gaps[$i]
));
$stmt=$pdo->prepare('updatetabletwo SET image\u id=image\u id-:i其中image\u id介于:lastpag和:lastId之间');
$stmt->execute(数组)(
“:i”=>$i,
“:lastGap”=>$lastGap,
“:lastId”=>$lastId
));
//确认一切都是正确的
$stmt=$pdo->exec('SELECT image_id FROM TableOne ORDER BY image_id ASC');
$stmt->bindColumn('image_id',$id);
if(!$stmt->fetch(PDO::fetch_-BOUND)){
抛出新异常('无行');//不应抛出
}
$lastId=$id;
while($stmt->fetch(PDO::fetch_-BOUND)){
如果($id!=($lastId+1)){
抛出新异常('id'.$lastId'和'.$id'之间存在错误);
}
$lastId=$id;
}
$stmt=$pdo->exec('SELECT image_id FROM TableTwo ORDER BY image_id ASC');
$stmt->bindColumn('image_id',$id);
if(!$stmt->fetch(PDO::fetch_-BOUND)){
抛出新异常('表2中没有行');//不应命中此异常
}
$lastId=$id;
$id=数组($id);
while($stmt->fetch(PDO::fetch_-BOUND)){
$id[]=$id;
如果(计数($id)==2){
如果($ids[0]!==$ids[1]){
抛出新异常(“ID上的表2错误”);
}
如果($ids[0]!==$lastId){
抛出新异常('id gapf上的表2错误
Insert into NewTable
Select id_image,foo,bar,@RowNumber := @RowNumber + 1 order by id_image.
try {
$pdo = new PDO('mysql:host=HOST;dbname=DB', 'user', 'pass');
$pdo->beginTransaction();
// Iterate through all id's in the first table
$stmt = $pdo->exec('SELECT image_id FROM TableOne ORDER BY image_id ASC');
$stmt->bindColumn('image_id', $id);
if(!$stmt->fetch(PDO::FETCH_BOUND)) {
throw Exception('No rows in table');
}
$lastId = $id;
$gaps = array();
// Find all the gaps
while($stmt->fetch(PDO::FETCH_BOUND)) {
if($id != ($lastId + 1)) {
$gaps[] = $id;
}
$lastId = $id;
}
if(!isset($gaps[0])) {
throw new Exception('No gaps found');
}
// For each gap, update the range from the last gap to that gap by subtracting
// the number of gaps there has been from the id
$lastGap = $gaps[0];
for($i = 1; $i < count($gaps); $i++) {
$stmt = $pdo->prepare('UPDATE TableOne SET image_id = image_id - :i WHERE image_id BETWEEN :lastGap AND :gap');
$stmt->execute(array(
':i' => $i,
':lastGap' => $lastGap,
':gap' => $gaps[$i]
));
$stmt = $pdo->prepare('UPDATE TableTwo SET image_id = image_id - :i WHERE image_id BETWEEN :lastGap AND :gap');
$stmt->execute(array(
':i' => $i,
':lastGap' => $lastGap,
':gap' => $gaps[$i]
));
$lastGap = $gaps[$i];
}
// Finally, fix the gap between the last found gap and the end of the table
$stmt = $pdo->prepare('UPDATE TableOne SET image_id = image_id - :i WHERE image_id BETWEEN :lastGap AND :gap');
$stmt->execute(array(
':i' => $i,
':lastGap' => $lastGap,
':gap' => $gaps[$i]
));
$stmt = $pdo->prepare('UPDATE TableTwo SET image_id = image_id - :i WHERE image_id BETWEEN :lastGap AND :lastId');
$stmt->execute(array(
':i' => $i,
':lastGap' => $lastGap,
':lastId' => $lastId
));
// Verify everything is correct
$stmt = $pdo->exec('SELECT image_id FROM TableOne ORDER BY image_id ASC');
$stmt->bindColumn('image_id', $id);
if(!$stmt->fetch(PDO::FETCH_BOUND)) {
throw new Exception('No rows'); // Should never be thrown
}
$lastId = $id;
while($stmt->fetch(PDO::FETCH_BOUND)) {
if($id != ($lastId + 1)) {
throw new Exception('There was an error between ids ' . $lastId . ' and '. $id);
}
$lastId = $id;
}
$stmt = $pdo->exec('SELECT image_id FROM TableTwo ORDER BY image_id ASC');
$stmt->bindColumn('image_id', $id);
if(!$stmt->fetch(PDO::FETCH_BOUND)) {
throw new Exception('No rows in table two'); // Shouldn't hit this
}
$lastId = $id;
$ids = array($id);
while($stmt->fetch(PDO::FETCH_BOUND)) {
$ids[] = $id;
if(count($ids) == 2) {
if($ids[0] !== $ids[1]) {
throw new Exception('Table two error on ids ');
}
if($ids[0] !== $lastId) {
throw new Exception('Table two error on id gapfix');
}
$lastId = $ids[0];
$ids = array();
}
}
$pdo->commit();
} catch(Exception $e) {
$pdo->rollBack();
var_dump($e);
}