ここでの基本的な考え方は、最初にすべてのギャップを見つけて、各IDをデクリメントする必要がある量を決定することです。次に、両方のテーブルを反復処理して、デクリメントを適用する必要があります。(追加する必要があります:host、db、user、pass、および実際のテーブル名)
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);
}
重要: これをファイルに入れてCLIを介して実行することをお勧めします。そのphp -f gapfix.php
前にクエリを含めると、$pdo->commit()
すべてのIDのリストが返されるため、操作が期待どおりに機能したことを確認できます。そうでない場合は、何も起こらなかったかのようにロールバックできます。 コードは、最初のテーブルが正しい順序であるかどうかをチェックするようになりました。ただし、2番目のテーブルはまだチェックされていません。 すべてのチェックが実装されました!