Авто инкремент после удалить в MySQL

У меня есть таблица MySQL с полем первичного ключа, которое имеет AUTO_INCREMENT. Прочитав другие сообщения здесь, я заметил людей с той же проблемой и с различными ответами. Некоторые рекомендуют не использовать эту функцию, другие утверждают, что она не может быть "исправлена".

Я:

table: course
fields: courseID, courseName

пример: количество записей в таблице: 18. Если я удалю записи 16, 17 и 18-я ожидал бы, что следующая запись будет иметь курс 16, однако это будет 19, потому что последний вошел идентификатор_курса было 18 лет.

мои знания SQL не удивительно, но есть ли в любом случае, чтобы обновить или обновить этот счет с помощью запроса (или настройки в интерфейсе phpMyAdmin)?

эта таблица будет относиться к другим в базе данных.


учитывая все советы, я решил игнорировать эту "проблему". Я просто удалю и добавлю записи, позволяя автоматическому приращению выполнять свою работу. Я думаю, что на самом деле не имеет значения, какой номер, так как это только используется как уникальный идентификатор и не имеет (как упоминалось выше) бизнес смысл.

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

16 ответов


что вы пытаетесь сделать, это очень опасно, так как это не целевое использование AUTO_INCREMENT.

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

сделайте шаг назад и спросите"почему вам нужно рециркулировать Ключевые значения? " Do unsigned INT (или BIGINT) не обеспечивают достаточно большое пространство ключей?

вы действительно собираетесь иметь больше чем 18,446,744,073,709,551,615 уникальные записи в течение всего срока службы вашего приложения?


ALTER TABLE foo AUTO_INCREMENT=1

Если вы удалили самые последние записи, это должно настроить его на использование следующего самого низкого доступного. Как и в, пока нет 19 уже, удаление 16-18 сбросит автоинкремент для использования 16.


EDIT: я пропустил бит о phpmyadmin. Вы можете установить его там, тоже. Перейдите на экран таблица и перейдите на вкладку Операции. Есть AUTOINCREMENT поле, которое вы можете установить на все, что вам нужно вручную.


первичные ключи автоинкремента в базе данных используются для уникальной идентификации данной строки и не должны быть заданы бизнес смысл. Поэтому оставьте первичный ключ как есть и добавьте другой столбец, например courseOrder. Затем, когда вы удаляете запись из базы данных, вы можете отправить дополнительную инструкцию UPDATE, чтобы уменьшить courseOrder столбец всех строк, которые имеют courseOrder больше, чем тот, который вы в настоящее время удаляете.

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


попробуй :

SET @num: = 0;

обновить your_table SET id = @num: = (@num+1);

ALTER TABLE tableName типа AUTO_INCREMENT = 1;

это сбросит значение autoincremented, а затем подсчитает каждую строку, пока для нее создается новое значение.

пример : до

  • 1 : первое значение здесь
  • 2 : второе значение здесь
  • X: удаленное значение
  • 4 : Остальная часть стола
  • 5: остальные остальные..

таким образом, таблица отобразит массив: 1,2,4,5

пример : После (если вы используете эту команду вы получите)

  • 1 : первое значение здесь
  • 2 : второе значение здесь
  • 3: остальная часть таблицы
  • 4: остальные остальные

нет трассировки удаленного значения, а остальная часть увеличенного продолжается с этот новый граф.

но

  1. если где-то в вашем коде что-то использует значение autoincremented... возможно, эта атрибуция вызовет проблемы.
  2. если вы не используете это значение в коде все должно быть ОК.

вы не должны полагаться на идентификатор AUTO_INCREMENT, чтобы сообщить вам, сколько записей у вас есть в таблице. Вы должны использовать SELECT COUNT(*) FROM course. Идентификаторы существуют для уникальной идентификации курса и могут использоваться в качестве ссылок в других таблицах, поэтому вы не должны повторять идентификаторы и не должны пытаться сбросить поле автоматического приращения.


вы можете выбрать идентификаторы, например:

set @rank = 0;
select id, @rank:=@rank+1 from tbl order by id

результатом является список идентификаторов и их позиции в последовательности.

вы также можете сбросить идентификаторы, например:

set @rank = 0;
update tbl a join (select id, @rank:=@rank+1 as rank from tbl order by id) b
  on a.id = b.id set a.id = b.rank;

вы также можете просто распечатать первый неиспользуемый идентификатор, например:

select min(id) as next_id from ((select a.id from (select 1 as id) a
  left join tbl b on a.id = b.id where b.id is null) union
  (select min(a.id) + 1 as id from tbl a left join tbl b on a.id+1 = b.id
  where b.id is null)) c;

после каждой вставки вы можете сбросить auto_increment:

alter table tbl auto_increment = 16

или явно установить значение id при выполнении вставки:

insert into tbl values (16, 'something');

обычно это не требуется, вы есть count(*) и возможность создания рейтингового номера в ваших результирующих наборах. типичный рейтинг может быть:

set @rank = 0;
select a.name, a.amount, b.rank from cust a,
  (select amount, @rank:=@rank+1 as rank from cust order by amount desc) b
  where a.amount = b.amount

клиенты, ранжированные по количеству потраченных средств.


Я пришел сюда в поисках ответа на главный вопрос "MySQL - Auto Increment after delete" но я мог найти ответ только на этот вопрос в вопросах

используя что-то вроде:

DELETE FROM table;
ALTER TABLE table AUTO_INCREMENT = 1;

отметим, что ответ Дарина Димитрова объяснить очень хорошо AUTO_INCREMENT и его использование. Взгляните прежде чем сделать что-то, о чем вы пожалеете.

PS: сам вопрос больше "Why you need to recycle key values?" и ответ Дольфа покроет.


Я получил очень простой, но сложный метод.

при удалении строки можно сохранить идентификаторы в другой временной таблице. После этого, когда вы вставите новые данные в основную таблицу, вы можете искать и выбирать идентификаторы из временной таблицы. Поэтому используйте проверку здесь. Если временная таблица не имеет идентификаторов, вычислите максимальный идентификатор в главной таблице и задайте новый идентификатор как:new_ID = old_max_ID+1.

NB: здесь нельзя использовать функцию автоматического приращения.


Я могу придумать множество сценариев, где вам может потребоваться это сделать, особенно во время миграции или процесса разработки. Например, мне только что пришлось создать новую таблицу, объединив две существующие таблицы (как часть сложного процесса настройки), а затем мне нужно было добавить первичный ключ после события. Вы можете удалить существующий столбец первичного ключа, а затем сделать это.

ALTER TABLE my_table ADD `ID` INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`ID`);

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


на самом деле есть способ исправить это. Сначала вы удаляете столбец первичного ключа auto_incremented, а затем добавляете его снова, например:

ALTER TABLE table_name DROP column_name;
ALTER TABLE table_name ADD column_name int not null auto_increment primary key first;

вы можете использовать программное обеспечение/скрипт клиента mysql, чтобы указать, откуда должен начинаться первичный ключ после удаления необходимых записей.


то, что вы пытаетесь сделать, это очень опасно. Подумай хорошенько. Существует очень веская причина для поведения автоматического приращения по умолчанию.

рассмотрим следующий пример:

запись удаляется в одной таблице, которая имеет отношение к другой таблице. Соответствующую запись во второй таблице не может быть удалена для проведения аудита. Эта запись становится потерянной из первой таблицы. Если новая запись вставлена в первую таблицу и последовательный первичный ключ используется, эта запись теперь связана с сиротой. Очевидно, это плохо. С помощью автоматического увеличения PK всегда гарантируется идентификатор, который никогда не использовался раньше. Это означает, что сироты остаются сиротами, и это правильно.


if($id == 1){ // deleting first row
            mysqli_query($db,"UPDATE employees  SET id=id-1 WHERE id>1");
        }
        else if($id>1 && $id<$num){ // deleting middle row
            mysqli_query($db,"UPDATE employees  SET id=id-1 WHERE id>$id");
        }
        else if($id == $num){ // deleting last row
            mysqli_query($db,"ALTER TABLE employees AUTO_INCREMENT = $num");
        }
        else{
            echo "ERROR";
        }

        mysqli_query($db,"ALTER TABLE employees AUTO_INCREMENT = $num");

вы можете подумать о создании триггера после удаления, чтобы вы могли обновить значение autoincrement и значение ID всех строк, которые не выглядят так, как вы хотели видеть.

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


его определенно не рекомендуется. Если у вас большая база данных с несколькими таблицами, возможно, вы сохранили идентификатор пользователя в таблице 2. если вы переставите таблицу 1, то, вероятно, предполагаемый идентификатор пользователя не будет являться идентификатором предполагаемой таблицы 2.


вот функция, которая исправит вашу проблему

    public static void fixID(Connection conn, String table) {

    try {
        Statement myStmt = conn.createStatement();
        ResultSet myRs;
        int i = 1, id = 1, n = 0;
        boolean b;
        String sql;

        myRs = myStmt.executeQuery("select max(id) from " + table);
        if (myRs.next()) {
            n = myRs.getInt(1);
        }
        while (i <= n) {
            b = false;
            myRs = null;
            while (!b) {
                myRs = myStmt.executeQuery("select id from " + table + " where id=" + id);
                if (!myRs.next()) {
                    id++;
                } else {
                    b = true;
                }
            }

            sql = "UPDATE " + table + " set id =" + i + " WHERE id=" + id;
            myStmt.execute(sql);
            i++;
            id++;
        }

    } catch (SQLException e) {
        e.printStackTrace();
    }
}