Подтвердить что ты не робот

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

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

У меня есть:

table: course
fields: courseID, courseName

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

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

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


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

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

4b9b3361

Ответ 1

То, что вы пытаетесь сделать, звучит опасно, поскольку это не предполагаемое использование AUTO_INCREMENT.

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

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

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

Ответ 2

ALTER TABLE foo AUTO_INCREMENT=1

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


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

Ответ 3

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

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

Ответ 4

Попробуйте:

SET @num: = 0;

UPDATE your_table SET id = @num: = (@num + 1);

ALTER TABLE tableName AUTO_INCREMENT = 1;

Это будет reset значение с автоинкрементами, а затем подсчет каждой строки, пока для него будет создано новое значение.

пример: перед

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

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

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

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

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

НО

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

Ответ 5

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

Ответ 6

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

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

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

вы также можете reset идентификаторы:

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

вы также можете просто распечатать первый неиспользуемый id следующим образом:

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;

после каждой вставки вы можете reset 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:[email protected]+1 as rank from cust order by amount desc) b
  where a.amount = b.amount

клиенты оцениваются по затраченной сумме.

Ответ 7

У меня очень простой, но хитрый метод.

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

Примечание. Вы не можете использовать функцию автоматического увеличения.

Ответ 8

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

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

DELETE FROM table;
ALTER TABLE table AUTO_INCREMENT = 1;

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

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

Ответ 9

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

Ответ 10

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

Рассмотрим это:

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

Ответ 11

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

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

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

Ответ 12

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

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

Ответ 13

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

Ответ 14

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

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

Ответ 15

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

Ответ 16

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

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