Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php MySQL修复两个表中的自动增量间隙_Php_Mysql_Database_Auto Increment - Fatal编程技术网

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);
    }