it-roy-ru.com

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

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

Я имею:

table: course
fields: courseID, courseName

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

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

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


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

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

60
OmidTahouri

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

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

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

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

66
Dolph
ALTER TABLE foo AUTO_INCREMENT=1

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


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

33
monksp

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

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

16
Darin Dimitrov

Пытаться :

SET @num: = 0;

ОБНОВЛЕНИЕ your_table SET id = @num: = (@ num + 1);

ALTER TABLE tableName AUTO_INCREMENT = 1;

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

пример: раньше

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

поэтому в таблице будет отображаться массив: 1,2,4,5

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

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

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

НО

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

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

3
Mike Sherov

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

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

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

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

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;

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

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:[email protected]+1 as rank from cust order by amount desc) b
  where a.amount = b.amount

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

2
user262976

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

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

DELETE FROM table;
ALTER TABLE table AUTO_INCREMENT = 1;

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

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

2
Michel Ayres

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

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

NB. Вы не можете использовать здесь функцию автоинкремента.

1
arefin2k

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

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

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

1
Peter Smartt

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

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

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

0
Sarfraz

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

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

0
Aloui Khalil

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

0
Joshua Omwoyo

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

    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();
    }
}
0
dani bilel
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");
0
Vaso Nadiradze

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

Учти это:

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

0
Charles Robertson