За последние 24 часа нас посетил 17551 программист и 1727 роботов. Сейчас ищут 996 программистов ...

Удаление "пробелов в нумерации" записей в таблице

Тема в разделе "PHP для новичков", создана пользователем Gabor, 31 авг 2009.

  1. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0
    Здравствуйте!

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

    Так вот:

    Имеется таблица с несколькими полями (в MySQL), нас интересует только одно из них, а именно поле "Id". В это поле автоматически записывается номер (автоинкремент) записи для данной строки в таблице. Имеется допустим 4 строки в таблице, тоесть у них номера записей таковы: 1,2,3,4. Допустим, что нужно удалить строку с Id=3. После удаления получается, что номера записей идут не по порядку, тоесть не 1,2,3,4 а 1,2,4.
    Я б хотел сделать так, чтоб после удаления записи(в данном случае №3), скрипт проверял порядок нумерации, и при наличии таких пропусков исправлял ситуацию, тоесть менял нумерацию с 1,2,4 на 1,2,3.
    ...да, надеюсь не слишком мутно написал :)

    Как мне объяснили знакомые, более (или менее) опытные программисты, штатных, встроенных команд у MySQL для подобного нет.

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

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    вы не должны этого хотеть.

    запись с ид=3 существовала и с ней происходили определенные события. Не надо перемешивать.
     
  3. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0
    Вспоминаю программиста нашей фирмы с Санкт-Петербурга, он на любую поставленную перед ним задачу отвечает вопросом "а зачем?", ну а я ему "Надо" :) Все же было бы очень приятно услышать ответ на вопрос, или хотя б какую либо конструктивную критику, а не только "тебе это не надо" (при всем уважении к Вашим знаниям уважаемый armadillo).
     
  4. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    ид означает УНИКАЛЬНЫЙ индекс, а не переходящий. иначе рассыпется связность данных. на ЭТОТ вопрос ответь - зачем?
     
  5. topas

    topas Активный пользователь

    С нами с:
    16 авг 2006
    Сообщения:
    2.258
    Симпатии:
    36
    [sql]
    DELTE FROM `some` WHERE `id` = 743;
    UPDATE `some` SET `id` = `id` - 1 WHERE id > 743
    [/sql]

    +1
     
  6. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0
    Я в курсе что такое "ИД" так как я сам создал в учебных целях эту таблицу, а на вопрос зачем ответ НАДО! С записью с ИД=3 никаких событий не происходило. Это просто таблица с несколькими строчками... Если Вам не трудно ответить на вопрос, то будьте добры сделайте это, ну а если нет, мне прийдется искать ответ самому. Не хочу "задираться", но разве нельзя просто ответить на вопрос? Технически это выполнимо (думаю что да)? Если да, то ответьте пожалуйста, и на этом будет тема закрыта.
     
  7. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    Gabor ты не прав. и это ТВОЯ проблема, и она тебе еще аукнется.

    долго.
    Gabor
    ты сначала напиши чего ты хочешь. сохранить порядок нумерования или нет.
     
  8. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0

    Нууу.... это не совсем то про что я думал, но наталкивает на определенные идеи. Если пропуск между соседними записями более чем 1, то нужно вычислить эту разницу, да и вообще для начала нужно определить где есть пробелы, а где их нет.
     
  9. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0
    Мне нужно именно то, чтоб нумерация была правильная, без пропусков. Я понимаю, что в определенных случаях, когда важно сохранить идентификатор записи (в учетных системах, где ИД это номер документа например) такое не пройдет, но в моем случае ИД не несет таких заданий на себе, это всего лишь номер строчки.
     
  10. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    вот в чем и проблема.
    "правильность" нумерации задает программист. Если у тебя не хватает мозгов описать, что тебе надо (на русском) - плати программисту и займись делом, которое тебе по силам.
    Именно потому, что ты не понимаешь, что и зачем ты делаешь, и возникают такие вопросы.

    тебе вообще пофиг на порядок следования или тебе надо, чтобы если и было a>b, то так и осталось?
     
  11. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Изменение поля id, которое обычно является уникальным и автоинкрементным крайне нежелательно.
    Но никто не запрещает ввести ещее одно поле, типа number, где указывать неразрывную цепочку и сделать его уникальным ключевым.
     
  12. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0
    Кажется я уже описал, что я имею введу под словом "правильность", а за "нет мозгов" отдельное спасибо.

    Пошел гуглить, до свидания.
     
  13. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0

    Как бы поле не называлось... а что если ИД есть всего лишь номером, а кроме него есть поле допустим "Код записи" которое и есть ключевым полем и не изменяется. Почему нельзя просто ответить на вопрос?
     
  14. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    так и не дошло...
     
  15. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0
    Ну так поясните пожалуйста, что ж я не понял?
     
  16. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Вообще ничего не понял

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

    А по поводу реализации - topas написал самое простое решение. Единственный его минус - это скорость. Особенно, если таблица большая.
     
  17. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
     
  18. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Зачем хлопать дверью? 90% головной боли от незнания каких-либо функций, непонимания основ или от того, что просто не приходит в голову более рационального алгоритма (или времени на него нет).
     
  19. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0
    Это вызвано моей неопытностью, учту и в будущем в подобных случаях буду называть поле иным именем, допустим тот же "nomer".

    Возможно я действительно не понимаю, поэтому опишу еще раз: если есть допустим 10 записей (1,2,3,... 10) и удалились номера с 4 по 9, нужно сделать так, чтоб запись номер 10 получила номер 4.

    Понял.
     
  20. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Вы знаете, сколько записей удаляете, а так же, знаете, начиная с какого номера удаляете.
    Итог:
    PHP:
    1.  
    2. <?php
    3. $delete = 6; // (с 4 по 9)
    4. $start = 4;
    5. $sql = 'UPDATE table SET number=number-'.$delete.' WHERE number > '.$start;


    Полное обновление нумерации:
    [sql]UPDATE my SET numner=(SELECT @numner:=@numner+1) WHERE @numner:=0[/sql]
     
  21. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    Gabor если есть записи 1,9,10, то обязательно, чтобы 9=>2, 10=>3, или можно наоборот?
     
  22. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0
    armadillo
    Первый вариант, тоесть 9=>2, 10=>3 (в данном случае получится, что 9=2 а 10=3).
     
  23. iliavlad

    iliavlad Активный пользователь

    С нами с:
    24 янв 2009
    Сообщения:
    1.689
    Симпатии:
    4
    Просто в следующий раз Вы будете проектировать таблицу по этому опыту и кто знает, что будет нести в себе ид.

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

    Поэтому лучше не исправлять ид, так как оно автоинкрементно. Лучше сделайте отдельное поле num или сделайте таблицу без поля id (раз уж оно вам не надо).
     
  24. Gabor

    Gabor Активный пользователь

    С нами с:
    9 мар 2008
    Сообщения:
    18
    Симпатии:
    0
    Мой опыт совсем маленький, но разве нельзя найти максимальное значение поля ИД (уже после изменения значений) и прибавив 1 получить следующее значение автоинкремента? Ну а вписать в базу можно довольно простым запросом.

    Ну а вот решение предложенное моим сотрудником: (НЕ КАЗНИТЕ!!! Он тоже не профессионал, просто любитель, продвинутее чем я, но любитель. Код возможно несовершенен, и выполнен в не особо профессиональном стиле, но работает!!!)

    Код (Text):
    1.  
    2. $q1=mysql_query("SELECT max(id) FROM table");
    3. $row=mysql_fetch_array($q1);
    4. $max=$row['max(id)'];
    5.  
    6. $koef=0;
    7.  
    8. echo '<br>';
    9. for ($i=1; $i<=$max; $i++)  {
    10.     $t=$i+$koef;
    11.    
    12.         $q2=mysql_query("SELECT id FROM table where id=".$i."");
    13.        
    14.         if (mysql_num_rows($q2)!=1) {
    15.             $koef=$koef-1;
    16.             //echo (' koef= '.$koef);
    17.             //echo '<br>';
    18.             }
    19.     $q3=mysql_query("UPDATE table SET id=".$t." WHERE id=".$i."");
    20. }
    21. $r=$t+1;
    22. echo $r;
    23. $q4=mysql_query("ALTER TABLE table PACK_KEYS =0 CHECKSUM =0 DELAY_KEY_WRITE =0 AUTO_INCREMENT =".$r."");
     
  25. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    уйду в монастырь. Женский наверно.