Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Как обновить значения в столбце AUTO_INCREMENT PRIMARY KEY после удаления записи из таблицы..
 
 автор: SilentChild   (17.04.2011 в 13:11)   письмо автору
 
 

Здравствуйте!

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

Вопрос, собственно, вот в чём.

Есть таблица. Первый столбец в ней определен так:


CREATE TABLE wall
(
    message_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ...
);


Таблица заполнена записями. Их там 100 штук и следовательно значение столбца `message_id` для последней записи будет равно 100. Я удалил 52-ю запись. После её удаления в столбце `message_id` остались записи со значениями от 1 до 51 и от 53 до 100.

Вопрос: Как сделать так, чтобы после удаления любой записи из таблицы все значения в столбце `message_id` сохраняли порядок и, следовательно, значение столбца `message_id` для последней записи соответствовало количеству записей в таблице?

P.S.: Я имею в виду есть ли какое-нибудь "волшебное" определение столбца, которое позволяет решить данную задачу без создания программного кода для вмешательства в каждую запись таблицы с SQL-запросом "UPDATE ... SET .... WHERE...." ?

  Ответить  
 
 автор: cheops   (17.04.2011 в 13:25)   письмо автору
 
   для: SilentChild   (17.04.2011 в 13:11)
 

Штатных средств для этого нет, более того, поддержание таких неразрывных последовательностей на базе первичного ключа с атрибутом AUTO_INCREMENT не поощряется. Так как цель AUTO_INCREMENT не нумерация строк (это выполняется отдельно в прикладном коде), а генерация уникальных значений. Более того это может приводить к нарушению ссылочной целостности. Например: спамер оставит сообщение на этом форуме и запись будет удалена со сдвигом значений первичных ключей, у всех тем, которые появились в промежутке между появлением спам-сообщения и событием удаления темы модератором, изменится первичный ключ. Поэтому ссылки, если на тему успели сослаться из вне, будут вести на совершенно другие темы. Именно поэтому старые значения AUTO_INCREMENT уничтоженных записей никогда больше не используются, новая запись - новая тема.

Какую цель преследуете? Может есть обходной путь, не затрагивающий первичный ключ)?

>поэтому осмелюсь создать новую тему.
Новых тем бояться не нужно, появился вопрос - смело заводите новую тему. Если был удачный ответ в прошлом, ссылку на старую тему обязательно приведут. В любом случае участники старой темы найдут её быстрее, чем вы, вот пусть они и ищут :)

  Ответить  
 
 автор: SilentChild   (17.04.2011 в 14:18)   письмо автору
 
   для: cheops   (17.04.2011 в 13:25)
 

Спасибо. Я понял о чем Вы говорите. Впредь для этой цели больше не буду использовать столбцы с определением AUTO_INCREMENT PRIMARY KEY.

Цель была в том, чтобы реализовать функцию удаления любого сообщения со стены сообщений. Чтобы удалить какое-то сообщение мне нужно знать номер записи в таблице, в которой это сообщение хранится. Потом использовать этот номер в SQL-запросе на удаление записи. Вот я и решил использовать столбец с AUTO_INCREMENT для отслеживания порядка записей в таблице, но как уже выяснилось не удачно.

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


CREATE TABLE wall
(
    ...
    number_of_row SMALLINT UNSIGNED NOT NULL,
    ...
);


... и программно с этим столбцом делать следующее...

При добавлении новой записи в таблицу:
- считываем значение порядкового номера предыдущей записи;
- увеличиваем его на единицу;
- присваиваем получившееся значение порядковому номеру новой записи.

При удалении любой записи из таблицы придется перезаписать ( уменьшить на один ) все значения столбца `number_of_row`, которые добавлялись позже удаляемой записи. Только такой способ приходит на ум.

  Ответить  
 
 автор: cheops   (17.04.2011 в 14:22)   письмо автору
 
   для: SilentChild   (17.04.2011 в 14:18)
 

Да, так обычно и поступают.

PS А нельзя использовать дату сообщений в качестве естественного столбца для сортировки? Обычно же новые сообщения помещаются либо в самое начало, либо в самый конец?

  Ответить  
 
 автор: SilentChild   (17.04.2011 в 14:59)   письмо автору
 
   для: cheops   (17.04.2011 в 14:22)
 

Точно, что-то я не подумал об этом. Выводить последовательно сообщения можно по дате. А удалять сообщение можно SQL-запросом с использованием значения столбца AUTO_INCREMENT PRYMARY KEY в качестве идентификатора записи, которую удаляем.

А если записи добавлены в одно и то же время, например ...

      
    message_id              message               message_time                
----------------------------------------------------------------------------------------   
         ...                 ...                            ...                            
         11               сообщение_11           2011-04-16 21:12:50        
         12               cообщение_12           2011-04-16 21:12:50         


...то каким будет вывод, если сортировка производится по дате?

Сообщения должны выводится в таком порядке (допустим):

21:12:49
сообщение_10

21:12:41
сообщение_9

21:12:20
сообщение_8
...
... и т.д

То есть по убыванию даты и времени.

  Ответить  
 
 автор: cheops   (17.04.2011 в 15:50)   письмо автору
 
   для: SilentChild   (17.04.2011 в 14:59)
 

Можно в ORDER BY добавить два столбца, сначала дату, потом message_id
SELECT * FROM tbl
ORDER BY message_time DESC, message_id DESC
В этом случае если попадется сообщение с той же датой, то будет выведено последнее добавленное в базу данных сообщение (впрочем это избыточно, если два сообщения добавлены одновременно, вряд ли нарушится смысл дискуссии, если одно сообщение будет прочитано раньше другого).

  Ответить  
 
 автор: SilentChild   (17.04.2011 в 15:53)   письмо автору
 
   для: cheops   (17.04.2011 в 15:50)
 

Огромное спасибо Вам за помощь! =)

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования