Как я могу сбросить автоинкремент MySQL, используя значение MAX из другой таблицы?

Я знаю, что это не сработает. Я пробовал его в разных формах и каждый раз терпел неудачу. Как проще всего добиться следующего результата?

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?

person ThinkCode    schedule 09.03.2010    source источник


Ответы (8)


Используйте подготовленный оператор:

  SELECT @max := MAX(ID)+ 1 FROM ABC;

  PREPARE stmt FROM 'ALTER TABLE ABC AUTO_INCREMENT = ?';
  EXECUTE stmt USING @max;

  DEALLOCATE PREPARE stmt;
person OMG Ponies    schedule 09.03.2010
comment
Звучит как довольно солидный ответ на мой вопрос! Благодарю вас! - person ThinkCode; 10.03.2010
comment
PREPARE stmt FROM 'ALTER TABLE XYZ AUTO_INCREMENT = ?' выдает мне ошибку :( - person bor; 02.08.2012
comment
Ошибка просто You have an error in your SQL syntax ... near '?' at line 1. Вы можете увидеть это в этой скрипте. Кажется, что ? не принимается в операторе PREPARE с AUTO_INCREMENT. В ответе Anurag есть обходной путь. - person T30; 16.11.2016
comment
@T30 У меня такая же ошибка с '?', я разместил обходной путь для этого здесь - person Saeid; 04.01.2017
comment
В ответе одна и та же таблица ABC используется как для получения MAX(ID), так и в подготовленном операторе для изменения таблицы. Это не вызывает фактически никаких изменений. @ThinkCode хотел установить auto_increment другой таблицы. - person Chetan Khilosiya; 29.08.2017
comment
Я использую MySQL 8 и получил ту же ошибку, что и @T30. Используя ответ Саида, это сработало. - person Gabe Gates; 15.10.2019
comment
@ChetanKhilosiya Вы не правы. Удаление из таблицы вызовет пробелы в идентификаторах, и если вы удалите с конца таблицы, MAX (ID) может быть намного ниже, чем AUTO_INCREMENT. - person Izzy; 05.08.2021

Следуя документации MySQL, это работал у меня в 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;
person Saeid    schedule 04.01.2017
comment
Может потребоваться SELECT COALESCE(MAX(id), 0) + 1 FROM ABC, если ABC — пустая таблица. - person John Vinopal; 14.06.2019

Я создаю сценарий автоматического преобразования базы данных для новой версии моего приложения.

В одной таблице мне нужно было изменить основное поле автоинкремента на другое поле. Поскольку эта страница появлялась первой много раз, пока я искал для нее решение, вот решение, которое в конечном итоге сработало для меня:

-- 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;
person user357516    schedule 03.06.2010

Любой, у кого возникли проблемы с 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
person Anurag    schedule 12.07.2013
comment
У меня были большие надежды на это, но я получаю эту ошибку: # 1064 - у вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MariaDB, на предмет правильного синтаксиса для использования рядом с «НАЧАТЬ ВЫБОР @max: = MAX (id) + 1 FROM test» в строке 2. - person kloddant; 13.12.2016
comment
Не хватает скобок в первой строке. Сделайте его СОЗДАТЬ ПРОЦЕДУРУ reset_xyz_autoincrement () - person Captain Payalytic; 14.03.2018

Сбросить идентификаторы автоинкремента.

Сбросить идентификаторы автоматического увеличения

Обновите все столбцы автоинкремента в базе данных до наименьшего возможного значения на основе текущих значений в базах данных. Нам нужно было сделать это после очистки базы данных.

Используйте подготовленное заявление в хранимая процедура:

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');
person Artistan    schedule 19.02.2015

Лично я бы, вероятно, использовал либо сценарий оболочки, либо небольшое приложение C#/C++, либо сценарий PHP/Ruby/Perl, чтобы сделать это за 2 запроса:

  • Возьмите нужное значение SELECT MAX(ID) FROM ABC;
  • Измените таблицу, используя значение ALTER TABLE XYZ AUTO_INCREMENT = <insert value retrieved from first query here>

Очевидно, нужно быть осторожным, чтобы новый автоматический приращение не вызвал каких-либо конфликтов ключей с существующими данными в таблице XYZ.

person Andy Shellam    schedule 09.03.2010
comment
Я думал, что это можно легко сделать, используя только запросы MySQL. Похоже, мне не повезло. Любое другое решение, использующее только MySQL - с использованием переменных в MySQL? Я хочу выполнить кучу запросов в одном файле .sql, а не в сценариях оболочки и сценариях Perl/Python. Спасибо за ответ. - person ThinkCode; 09.03.2010

Хорошо, ребята. Я придумал не очень интуитивное решение. Самое приятное, что это работает!

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);
person ThinkCode    schedule 09.03.2010
comment
Откуда взялся ContactID? - person T30; 11.11.2016

Если вы действительно хотите сделать это только в 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
person Ike Walker    schedule 09.03.2010