SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 06.03.2010 21:25:11

Mirexzpalich
Завсегдатай
Зарегистрирован: 03.03.2010
Сообщений: 26

Автозаполнение

создат таблицу:
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?

Неактивен

 

#2 06.03.2010 22:18:35

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Автозаполнение

>Получил таблицу:

Приведите запрос получения данных. Подозреваю, что Вы использовали 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       |
|----------------|


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#3 06.03.2010 22:37:58

Mirexzpalich
Завсегдатай
Зарегистрирован: 03.03.2010
Сообщений: 26

Re: Автозаполнение

Да. Для вывода я использовал:
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)

Неактивен

 

#4 07.03.2010 00:18:50

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Автозаполнение

Ну тогда 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? Чем смущает то, что будут зазоры встречаться?


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#5 07.03.2010 05:16:41

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Автозаполнение

Немного от себя добавлю.

Стремление сделать id красивыми — это человеческое. Люди вообще любят
красивое. Но id — это машинное, а не человеческое. Человеческое — это
как раз имя. Поэтому нужно заставлять себя не путать эти понятия. Предла-
гаю Вам, например, вставить первую запись с id = 159 для того, чтобы не
иметь предрасположенности к заполнению дырок в последовательности id wink

Неактивен

 

#6 07.03.2010 16:37:48

Mirexzpalich
Завсегдатай
Зарегистрирован: 03.03.2010
Сообщений: 26

Re: Автозаполнение

deadka написал:

А вообще, позвольте поинтересоваться, к чему вам такая "неразрывная" последовательность id? Чем смущает то, что будут зазоры встречаться?

Просто нравитя когда все ровно. Вот и не охото иметь разрывов.

Респект всем кто откликнулся. Просто хотелось узнать есть ли такие команды. Оказывается нет. И нужен целый алгоритм. Я свою дазу связываю с PHP и нарвался на небольшую проблему, когда узнал, что id имеет разрывы.

У меня вот такая идея. Если мы будем перебирать id от 1. И смотреть есть ли запись с таким id, если есть идем дальше, если нет то новой записи id присваиваем.

Как вы думаете, сильно ли этот алгоритм повлияет на быстродействие, если в базе большое количество записей?

Неактивен

 

#7 07.03.2010 19:09:05

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Автозаполнение

Ну, если Вы всегда будете идти от единицы, то, очевидно, будет влиять,
т.к. Вам нужно будет *всегда* читать *всю* таблицу *построчечно* *от-
дельными запросами*. Более того, Ваш алгоритм подвержен race condi-
tion, т.е. если Вы попробуете одновременно вставить две независимые
строки, то они попытаются вставить записи с одинаковыми id.

Неактивен

 

#8 07.03.2010 19:17:24

Mirexzpalich
Завсегдатай
Зарегистрирован: 03.03.2010
Сообщений: 26

Re: Автозаполнение

race condition отпадает. у меня всегда вставляется 1 строка.
То что влиять будет это сразу ясно. Вопрос в том на сколько сильно!

Отредактированно Mirexzpalich (07.03.2010 19:18:15)

Неактивен

 

#9 07.03.2010 19:28:28

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Автозаполнение

Линейно smile

Неактивен

 

#10 08.03.2010 09:09:30

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Автозаполнение

> Просто нравитя когда все ровно. Вот и не охото иметь разрывов.

id в базе данных - не тот случай, когда нужно ориентироваться на "ровно". Если вы опасаетесь переполнения счетчика, то возьмите восьмибайтный беззнаковый целый тип - хватит, мягко скажем,  за глаза :-)).

Что касается

"
У меня вот такая идея. Если мы будем перебирать id от 1. И смотреть есть ли запись с таким id, если есть идем дальше, если нет то новой записи id присваиваем.
"

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

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

Да, кстати, перебирать лучше не от единицы (вдруг нет в базе такого id), а начать с минимального id в базе " select min(id) from t "


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#11 08.03.2010 15:34:09

Mirexzpalich
Завсегдатай
Зарегистрирован: 03.03.2010
Сообщений: 26

Re: Автозаполнение

Спасибо. За овет. Буду эксперементировать всеми способами.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson