【问题标题】:How can I reset an MySQL AutoIncrement using a MAX value from another table?如何使用另一个表中的 MAX 值重置 MySQL AutoIncrement?
【发布时间】:2011-01-25 12:35:22
【问题描述】:

我知道这行不通。我以各种形式尝试过,但都失败了。实现以下结果的最简单方法是什么?

ALTER TABLE XYZ AUTO_INCREMENT = (select max(ID) from ABC);

这非常适合自动化项目。

SELECT @max := (max(ID)+1) from ABC;        -> This works!
select ID from ABC where ID = (@max-1);     -> This works!
ALTER TABLE XYZ AUTO_INCREMENT = (@max+1);  -> This fails :( Why?

【问题讨论】:

    标签: sql mysql auto-increment reset


    【解决方案1】:

    使用prepared statement

      SELECT @max := MAX(ID)+ 1 FROM ABC;
    
      PREPARE stmt FROM 'ALTER TABLE ABC AUTO_INCREMENT = ?';
      EXECUTE stmt USING @max;
    
      DEALLOCATE PREPARE stmt;
    

    【讨论】:

    • 对于我的问题来说,这听起来像是一个非常可靠的答案!谢谢!
    • PREPARE stmt FROM 'ALTER TABLE XYZ AUTO_INCREMENT = ?' 为我生成错误:(
    • 错误只是You have an error in your SQL syntax ... near '?' at line 1。您可以在this fiddle 中看到它。似乎? 在带有AUTO_INCREMENT 的PREPARE 语句中不被接受。 Anurag 答案有一个解决方法。
    • @T30 '?' 出现同样的错误,我已经发布了解决此问题的方法here
    • 在答案中,同一个表 ABC 用于获取 MAX(ID) 和在准备好的语句中更改表。这实际上不会导致任何变化。 @ThinkCode 想设置另一个表的 auto_increment。
    【解决方案2】:

    按照the MySQL documentation,这在 MySQL 5.7 中对我有用:

    SET @m = (SELECT MAX(id) + 1 FROM ABC);
    SET @s = CONCAT('ALTER TABLE XYZ AUTO_INCREMENT=', @m);
    PREPARE stmt1 FROM @s;
    EXECUTE stmt1;
    DEALLOCATE PREPARE stmt1;
    

    【讨论】:

    • 如果 ABC 是空表,可能需要SELECT COALESCE(MAX(id), 0) + 1 FROM ABC
    【解决方案3】:

    PREPARE stmt FROM 'ALTER TABLE XYZ AUTO_INCREMENT = ?' 遇到问题的人可以使用:

    CREATE PROCEDURE reset_xyz_autoincrement
    BEGIN
          SELECT @max := MAX(ID)+ 1 FROM ABC;
          set @alter_statement = concat('ALTER TABLE temp_job_version AUTO_INCREMENT = ', @max);
          PREPARE stmt FROM @alter_statement;
          EXECUTE stmt;
          DEALLOCATE PREPARE stmt;
    END
    

    【讨论】:

    • 我对这个寄予厚望,但我得到了这个错误:#1064 - 你的 SQL 语法有错误;检查与您的 MariaDB 服务器版本相对应的手册,以在第 2 行的“BEGIN SELECT @max := MAX(id)+ 1 FROM test”附近使用正确的语法
    • 第一行缺少括号。将其设为“CREATE PROCEDURE reset_xyz_autoincrement ()”
    【解决方案4】:

    我正在为我的应用程序的新版本创建一个自动数据库转换脚本。

    在一个表中,我需要将主自动增量字段更改为另一个字段。由于此页面在我搜索解决方案时首先出现了很多次,所以这里有一个最终对我有用的解决方案:

    -- Build a new ID field from entry_id, make it primary and fix the auto_increment for it:
    ALTER TABLE  `entries` ADD  `id` INT UNSIGNED NOT NULL FIRST;
    UPDATE entries SET id = entry_id;
    ALTER TABLE  `entries` ADD PRIMARY KEY (  `id` );
    
    -- ...the tricky part of it:
    select @ai := (select max(entry_id)+1 from entries);
    set @qry = concat('alter table entries auto_increment=',@ai);
    prepare stmt from @qry; execute stmt;
    
    -- ...And now it's possible to switch on the auto_increment:
    ALTER TABLE  `entries` CHANGE  `id`  `id` INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT;
    

    【讨论】:

      【解决方案5】:

      重置自动增量 ID。

      Reset Auto Increment IDs

      根据数据库中的当前值将数据库中的所有自动增量列更新为可能的最小值。我们需要在清理数据库后执行此操作。

      stored procedure 中使用prepared statement

      drop PROCEDURE if exists reset_autoincrement;
      DELIMITER //
      CREATE PROCEDURE reset_autoincrement (IN schemaName varchar(255))
       BEGIN
          DECLARE done INT DEFAULT FALSE;
          DECLARE o_name VARCHAR(255);
          DECLARE o_table VARCHAR(255);
          DECLARE cur1 CURSOR FOR SELECT COLUMN_NAME, TABLE_NAME FROM information_schema.`COLUMNS` WHERE extra LIKE '%auto_increment%' and table_schema=schemaName;
          DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
          OPEN cur1;
          read_loop: LOOP
           FETCH cur1 INTO o_name, o_table;
      
           IF done THEN
             LEAVE read_loop;
           END IF;
      
        set @qry1 = concat('SELECT MAX(`',o_name,'`) + 1 as autoincrement FROM `',o_table,'` INTO @ai');
        PREPARE stmt1 FROM @qry1;
        EXECUTE stmt1;
      
        IF @ai IS NOT NULL THEN
            SELECT  o_name, o_table;
         select @qry1;
         select @ai;
         set @qry2 = concat('ALTER TABLE `',o_table,'` AUTO_INCREMENT = ', @ai);
         select @qry2;
         PREPARE stmt2 FROM @qry2;
         EXECUTE stmt2;
        END IF;
      
          END LOOP;
      
          CLOSE cur1;
       END //
      DELIMITER ;
      
      
      call reset_autoincrement('my_schema_name');
      

      【讨论】:

        【解决方案6】:

        我个人可能会使用一个 shell 脚本或一个小 C#/C++ 应用程序或 PHP/Ruby/Perl 脚本在 2 个查询中执行此操作:

        • 获取你想要的值SELECT MAX(ID) FROM ABC;
        • 使用值ALTER TABLE XYZ AUTO_INCREMENT = <insert value retrieved from first query here> 更改表

        显然要小心,新的自动增量不会导致任何键与XYZ 表中的现有数据发生冲突。

        【讨论】:

        • 我认为只使用 MySQL 查询就可以轻松完成。看来我运气不好。仅使用 MySQL 的任何其他解决方案 - 在 MySQL 中使用变量?我想在一个 .sql 文件中执行一堆查询,而不是 shell 脚本和 Perl/Python 脚本。感谢您的回答。
        【解决方案7】:

        好的,伙计们。我想出了一个不太直观的解决方案。最好的部分是它有效!

        SELECT @max := max(ID) from ABC;       
        ALTER TABLE XYZ AUTO_INCREMENT = 1;
        ALTER TABLE XYZ ADD column ID INTEGER primary key auto_increment;
        UPDATE XYZ SET ContactID = (ContactID + @max);
        

        【讨论】:

        • ContactID 来自哪里?
        【解决方案8】:

        如果您真的想单独在 MySQL 中执行此操作,您可以将动态构建的 alter 命令转储到磁盘上的文件中,然后执行它。

        像这样:

        select concat('ALTER TABLE XYZ AUTO_INCREMENT = ',max(ID)+1,';') as alter_stmt
        into outfile '/tmp/alter_xyz_auto_increment.sql'
        from ABC;
        
        \. /tmp/alter_xyz_auto_increment.sql
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-12-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-26
          • 2020-03-17
          • 2019-09-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多