Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MySQL > Экономия id (присваивание удаленных id)


Автор: Zerstroer 11.3.2011, 13:29
Здравствуйте уважаемые.
Возникла тривиальная задача. 
Есть таблица, в ней есть поле с идентификаторами. Поле, условно AUTO_INCREMENT (но необязательно)
Возникает такая ситуация:
В таблице есть записи с id = 1, id =2, id = 3, id =4 (и т.д.)
После чего мы удалили записи с id = 2 и id = 3.
В соответствии с AUTO_INCREMENT следующая добавленная запись будет иметь id = 5.
Но! Тут возникает непростая и странная необходимость - следующая добавленная запись должна иметь id = 2.
В связи с чем, обращаюсь к вам с вопросом:
Имеется ли в MySQL версии 5.1 функционал позволяющий присваивать вновь добавляемым записям наименьший из удаленных идентификаторов?

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

Спасибо, жду ответов.

Автор: Akina 11.3.2011, 14:11
Подобные действия идеологически неправильны и находятся в вопиющем противоречии с существующими нормами.
Если нужно - заведи дополнительное поле, и в нём строй непрерывные идентификаторы. А ключевое поле не трогай.
PS. Вопрос уже обсуждался - в поиск плиз.

Автор: skyboy 11.3.2011, 14:15
Цитата(Zerstroer @  11.3.2011,  12:29 Найти цитируемый пост)
В правильном ли направлении в данной ситуации мыслю?

нет.
автоинкрементное поле - это ключ(не совсем корректное тождество, но в том же mysql автоинкрементное поле обязано быть указанным и как primary key), механизм обеспечения целостности.
по этой причине в принцип работы этого механизма(последовательное увеличение с игнорированием удаленных значений) вмешиваться без очень-очень-очень уважительных причин не надо.
для чего ты это поле используешь, что тебя беспокоят "дырки"? для нумерации при выводе?

Автор: Zerstroer 11.3.2011, 23:51
skyboy, нет. Меня не беспокоят "дырки", я в курсе об идеологическом противоречии механизму обеспечения целостности. Я даже думал, что неправильно поставил вопрос, но уважаемый Akina меня все таки неправильно понял. Я говорил о поле AUTO_INCREMENT, как о поле содержащем ИДЕНТИФИКАТОРЫ, а не как о ключевом поле.
Эта таблица не связана по полю id ни с одним другим, т.е. по факту это поле ключом НЕ ЯВЛЯЕТСЯ и являться не будет.
Разъясню ситуацию. 
В этой таблице должна дублироваться информация из некоего файла, заполняемого сторонним приложением. Некое приложение записывает данные в файл, причем там (в файле) есть колонка, идентичная описанному мной id и заполняется она как раз с заполнением "дырок". Моя задача заполнить мою таблицу с использованием такого же принципа заполнения "дырок" как и в программе, заполняющей файл. Надеюсь, всё понятно объяснил.
Из 
Цитата(skyboy @  11.3.2011,  12:15 Найти цитируемый пост)
mysql автоинкрементное поле обязано быть указанным и как primary key

следует, что в Mysql отсутствует механизм генерации идентификаторов с заполнением "дырок". Верно ли я понял?
Следовательно:
Цитата(Zerstroer @  11.3.2011,  11:29 Найти цитируемый пост)
это должно решаться написанием хранимой функции, перебирающей с наименьшего все id в данной таблице и возвращающей первый недостающий

верное ли решение я принимаю?

Автор: bars80080 12.3.2011, 00:30
Цитата(Zerstroer @  11.3.2011,  22:51 Найти цитируемый пост)
Эта таблица не связана по полю id ни с одним другим, т.е. по факту это поле ключом НЕ ЯВЛЯЕТСЯ и являться не будет.
Разъясню ситуацию. 
В этой таблице должна дублироваться информация из некоего файла, заполняемого сторонним приложением

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

последуй совету:
Цитата(Akina @  11.3.2011,  13:11 Найти цитируемый пост)
Если нужно - заведи дополнительное поле, и в нём строй непрерывные идентификаторы

всё

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

Автор: Akina 12.3.2011, 10:13
Цитата(Zerstroer @  12.3.2011,  00:51 Найти цитируемый пост)
В этой таблице должна дублироваться информация из некоего файла, заполняемого сторонним приложением. Некое приложение записывает данные в файл, причем там (в файле) есть колонка, идентичная описанному мной id и заполняется она как раз с заполнением "дырок". Моя задача заполнить мою таблицу с использованием такого же принципа заполнения "дырок" как и в программе, заполняющей файл. 

Ну так и берите номера из файла. Зачем делать то, что уже сделано?

Автор: skyboy 12.3.2011, 12:39
нифига не понятно.
если надо то же, что и в файле - бери из файла.
если надо так же, как и в файле - нумеруй уже после выборки.

Автор: Zerstroer 13.3.2011, 09:45
Занесение информации в таблицу должно осуществляться исключительно средствами MySQL. У меня есть только доступ к базе и нет доступа к программе. Заполняться таблица будет с помощью триггеров, навешаных на другую таблицу, с которой работает приложение, заполняющее файл. В общем, все действительно хитровымудрено, но на свои изначальные вопросы ответы я уже нашел.

Автор: Zerstroer 18.3.2011, 23:36
Если кому интересно, то написал процедурку под свои извращения, позволяющую выбирать наименьшее пропущенное целое значение из последовательных значений в заданной колонке заданной таблицы.
Скрипт с примером использования в конце.
Код

DROP PROCEDURE IF EXISTS econoid;
DELIMITER ??
CREATE PROCEDURE econoid(INOUT variable INT, IN table_name VARCHAR(100), IN column_name VARCHAR(100))
BEGIN
SET @i := 0; /*Основное возвращаемое значение*/
SET @C := 1;
SET @B :=0;
SET @que = CONCAT('SET @B := EXISTS(SELECT * FROM ', table_name,' WHERE ', column_name,' = @i);');
PREPARE q_ps FROM @que;
WHILE @C = 1 DO    
    EXECUTE q_ps;
  IF @B /*EXISTS(SELECT * FROM actions WHERE actionid = @i)*/ THEN 
        SET @i := @i + 1;
    ELSE  
         SET @C := 0;
  END IF;  
END WHILE;
SET variable := @i;
END??
DELIMITER ;

SET @V = 0;
CALL econoid(@V, 'actions','actionid');
SELECT @V;


Автор: Zloxa 18.3.2011, 23:52
Цитата(Zerstroer @  18.3.2011,  23:36 Найти цитируемый пост)
выбирать наименьшее пропущенное целое значение из последовательных значений в заданной колонке заданной таблицы.

Код

SELECT t1.column_name + 1 
 FROM  table_name t1 
 left join table_name t2 on t2.column_name = t1.column_name + 1
 where t2.column_name is null
 order by t1.column_name
 limit 1

Код

SELECT t1.column_name + 1 
 FROM  table_name t1 
 where not exists (select null from table_name t2 where  t2.column_name = t1.column_name + 1)
 order by t1.column_name
 limit 1


Автор: Zerstroer 23.3.2011, 13:19
Zloxa, молча апплодирую стоя в углу на коленях на рассыпаной соли... и плачу от красоты...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)