Задавайте вопросы, мы ответим
Вы не зашли.
создат таблицу:
create table man
(
name VARCHAR(20) NOT NULL,
id INT UNSIGNED NOT NULL AUTO_INCREMENT
);
Добавил записи:
insert into man(name) values('Kola');
insert into man(name) values('Mixa');
Получил таблицу:
|----------------|
| name | id |
|----------------|
| Kola | 1 |
| Mixa | 2 |
|----------------|
После удаления:
DELETE FROM man WHERE id=1;
Полуил:
|----------------|
| name | id |
|----------------|
| Mixa | 2 |
|----------------|
Снова добавляю:
insert into man(name) values('Kola');
Получаю
|----------------|
| name | id |
|----------------|
| Mixa | 2 |
| Kola | 3 |
|----------------|
А можно ли сделать так, чтобы получилось как было в начале? :
|----------------|
| name | id |
|----------------|
| Kola | 1 |
| Mixa | 2 |
|----------------|
AUTO_INCREMENT просто при добавлении id новой записи увеличивает на 1?
Неактивен
>Получил таблицу:
Приведите запрос получения данных. Подозреваю, что Вы использовали select * from man, из этого и будем исходить.
> А можно ли сделать так, чтобы получилось как было в начале?
Если вы имеете в виду, чтобы select * from man выдавал записи в том же порядке, то вряд ли, потому что после новой вставки Kola в таблице находится позже чем Miha.
Да и в принципе, если нужно извлекать данные в определенном порядке, то лучше использовать сортировки (order by) по какому-то критерию (допустим завести для этого еще один столбец, где хранить критерий сортировки) - если вы не задаете критерий сортировки при select, то трудно точно прогнозировать в каком порядке mysql выдаст данные из таблицы.
> AUTO_INCREMENT просто при добавлении id новой записи увеличивает на 1?
Да. Только увеличивает на 1 не от id последней текущей записи, а от той, которая "в принципе" уже была в этой таблице. Т. е. если бы вы после создания таблицы и первоночального заполнения удалили бы строку, где id равен 2 (а не 1, как у вас), и после этого добавили бы новую запись, то содержимое было бы
|----------------|
| name | id |
|----------------|
| Kola | 1 |
| Mixa | 3 |
|----------------|
Неактивен
Да. Для вывода я использовал:
select * from man;
Про AUTO_INCREMENT я понял. Попробую задать вопрос по другому
Если у меня в начале столбец id (select id from man;):
id
1
2
3
4
5
Потом я удалю:
DELETE FROM man WHERE id=2;
DELETE FROM man WHERE id=4;
Получу:
id
1
3
5
Сново добавлю:
insert into man(name) values('Kola');
insert into man(name) values('Ka');
То получу
id
1
3
5
6
7
Мне же надо, что бы вышло:
id
1
3
5
2
4
Т.е. чтобы не было разрыва в значениях id (не 1..3..567 а 13524), чтобы для новых записей в столбце id устанавливалось минимальное, не повторяющееся значение большее нуля.
Отредактированно Mirexzpalich (06.03.2010 22:40:46)
Неактивен
Ну тогда auto_increment в его обычном назначении точно использовать не получится.
Боюсь, что придется в таком случае каким-либо хитрым запросом (пример приведен ниже) выискивать "зазоры" между идущими подряд id-шниками и вставлять туда записи.
Пример:
create table t(id int);
insert into t values(1),(2),(3),(5),(6),(9);
результат:
mysql> select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 5 |
| 6 |
| 9 |
+------+
6 rows in set (0.00 sec)
Далее создаем выборку, в которой есть еще один столбец, который содержит значения id, только следующие по списку
mysql> set @i=null;
Query OK, 0 rows affected (0.00 sec)
mysql> select @i id, @i:=`id` `nextid` from `t`;
+------+--------+
| id | nextid |
+------+--------+
| NULL | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 5 |
| 5 | 6 |
| 6 | 9 |
+------+--------+
6 rows in set (0.00 sec)
и из этой выборки уже ищем тот id, разница у которого со следующим не равна единице
запрос:
mysql> set @i=null;
Query OK, 0 rows affected (0.00 sec)
mysql> select id+1 as needid from ( select @i id, @i:=`id` `nextid` from `t`) t1 where not (nextid-id=1) limit 1;
+--------+
| needid |
+--------+
| 4 |
+--------+
1 row in set (0.00 sec)
имеем результирующий 4 - вот он и есть пропущенный.
Ну а далее вставляем запись в таблицу, явно указывая этот id.
Может быть можно как-то проще, но я не знаю как :-). Более подробное описание приема (респект rgbeast'у и vasye) вот здесь: http://sqlinfo.ru/forum/viewtopic.php?id=2170.
А вообще, позвольте поинтересоваться, к чему вам такая "неразрывная" последовательность id? Чем смущает то, что будут зазоры встречаться?
Неактивен
Немного от себя добавлю.
Стремление сделать id красивыми — это человеческое. Люди вообще любят
красивое. Но id — это машинное, а не человеческое. Человеческое — это
как раз имя. Поэтому нужно заставлять себя не путать эти понятия. Предла-
гаю Вам, например, вставить первую запись с id = 159 для того, чтобы не
иметь предрасположенности к заполнению дырок в последовательности id
Неактивен
deadka написал:
А вообще, позвольте поинтересоваться, к чему вам такая "неразрывная" последовательность id? Чем смущает то, что будут зазоры встречаться?
Просто нравитя когда все ровно. Вот и не охото иметь разрывов.
Респект всем кто откликнулся. Просто хотелось узнать есть ли такие команды. Оказывается нет. И нужен целый алгоритм. Я свою дазу связываю с PHP и нарвался на небольшую проблему, когда узнал, что id имеет разрывы.
У меня вот такая идея. Если мы будем перебирать id от 1. И смотреть есть ли запись с таким id, если есть идем дальше, если нет то новой записи id присваиваем.
Как вы думаете, сильно ли этот алгоритм повлияет на быстродействие, если в базе большое количество записей?
Неактивен
Ну, если Вы всегда будете идти от единицы, то, очевидно, будет влиять,
т.к. Вам нужно будет *всегда* читать *всю* таблицу *построчечно* *от-
дельными запросами*. Более того, Ваш алгоритм подвержен race condi-
tion, т.е. если Вы попробуете одновременно вставить две независимые
строки, то они попытаются вставить записи с одинаковыми id.
Неактивен
race condition отпадает. у меня всегда вставляется 1 строка.
То что влиять будет это сразу ясно. Вопрос в том на сколько сильно!
Отредактированно Mirexzpalich (07.03.2010 19:18:15)
Неактивен
Линейно
Неактивен
> Просто нравитя когда все ровно. Вот и не охото иметь разрывов.
id в базе данных - не тот случай, когда нужно ориентироваться на "ровно". Если вы опасаетесь переполнения счетчика, то возьмите восьмибайтный беззнаковый целый тип - хватит, мягко скажем, за глаза :-)).
Что касается
"
У меня вот такая идея. Если мы будем перебирать id от 1. И смотреть есть ли запись с таким id, если есть идем дальше, если нет то новой записи id присваиваем.
"
то лучше воспользоваться тем механизмом, который приведен выше, быстрее получится.
Ради эксперимента создайте тестовую таблицу, вставьте туда побольше записей и сравните скорость поиска первого свободного элемента путем перебора, как планируете вы и путем указанного механизма.
Да, кстати, перебирать лучше не от единицы (вдруг нет в базе такого id), а начать с минимального id в базе " select min(id) from t "
Неактивен
Спасибо. За овет. Буду эксперементировать всеми способами.
Неактивен