Emp*_*ger 5 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 8 21
3 17 81
7 29 50
7 1 14
8 10 26
8 27 34
Run Code Online (Sandbox Code Playgroud)
id_image第一张表中的自动增量存在差距.在第二个表中,id_image引用id_image第一个表中的每个ID,其中有两个ID.
注意:这个表是理论上的.我不知道其中的差距是完全,或无论是否有甚多的差距.我所知道的是第一个值是1,最后一个值高于总行数.
现在,我想解决这个问题.
在你说差距无关紧要之前,如果他们这样做,这是糟糕的数据库设计,让我告诉你; 我同意你的看法.
但是,我正在处理的是一个(绝望的后端倒退)第三方开源系统,我需要将大量现有数据导入到多个表中,这些数据没有交叉引用的ID.我可以确保相同的数据在整个系统的每个表中获得匹配ID的唯一方法是按顺序输入它,这意味着我不能有间隙.
所以我现在需要做的是;
id_image第一个表中列的间隙,以便最后一个值与行计数匹配.id_image第二个表中的列,使其值对应于相同的行对应于间隙修复之前.我该如何开始这样做?我知道这可能超出了MySQL查询语言的功能,因此PHP答案也是可以接受的.谢谢!:)
这里的基本思想是首先找到所有的间隙,以确定每个 id 需要减少多少。然后,您必须迭代两个表并应用减量。(您需要添加:主机、数据库、用户、通行证和实际的表名称)
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);
}
Run Code Online (Sandbox Code Playgroud)
重要的: 您可能希望将其放入文件中并通过 CLI 运行:并在返回所有 id 列表 php -f gapfix.php之前包含一个查询,以便您可以验证操作是否按预期工作。$pdo->commit()如果没有,您可以将其回滚,就像什么都没发生一样。现在,代码会自行检查第一个表的顺序是否正确。然而它还没有检查第二个表。 所有检查均已落实!