Как стать автором
Обновить

Комментарии 107

НЛО прилетело и опубликовало эту надпись здесь
Да вообще не понятно зачем этот код вообще, если все эти действия реализуются одной строчкой :)
Ну подобный код я встречал многократно и у вполне российских программистов :)
Да, неэффективно. Да, немногопоточно. Да, для этого есть автоинкременты или генераторы.
А как сделать это одной строчкой? (Ну если отбросить в строну тот факт, что так делать вообще нельзя.)
mysql_insert_id — Get the ID generated from the previous INSERT operation - код не об этом ? :)
НЛО прилетело и опубликовало эту надпись здесь
Именно об этом
НЛО прилетело и опубликовало эту надпись здесь
В данном случае, не только скрипт кривой, но и база спроектирована неверно. В ней поле id без auto_increment. Поэтому товарищ так извращается для получения следующего id для юзера, вместо mysql_insert_id
НЛО прилетело и опубликовало эту надпись здесь
>В данном случае, не только скрипт кривой, но и база >спроектирована неверно. В ней поле id без auto_increment.
Слышали о SQLite 2 ? вот там auto_increment нет.
>Поэтому товарищ так извращается для получения следующего id для >юзера, вместо mysql_insert_id
mysql_insert_id возвращает ID, сгенерированный колонкой с AUTO_INCREMENT последним запросом INSERT к серверу
у нас тут нет AUTO_INCREMENT это раз, во вторых мы можем добавить юзера а потом еще сотню записей, а нам надо именно ID для нового ЮЗЕРА узнать, так что тоже не подходит ваш совет.
ааа-а-а-а извиняюсь, только ща увидел что юзается именно mysql_query :)
ага, только хотел написать, не смущают ли вас приставки mysql* в названии функций :)
такой код пишут для переносимости на разные базы данных. Не во всех же есть автоинкременты (К примеру cmf drupal, там есть целая таблица - последовательности для этих целей)
НЛО прилетело и опубликовало эту надпись здесь
autoincrement поля заполняются сами, если не передавать в INSERT их значения.
автоинкремент использовать Шива не велит
Ганеш наоборот всеми лапами и хоботом ЗА! :)
Скорее Брахма (создатель) или Вишну (хранитель). Шива - Бог разрушения, его при программировании призывать не следует)
а вы Snow Сrash не читали? там про Шиву есть :)
Я нигде не противоречу. При регистрации юзера надо заполнить табличку, кроме прочих данных, необходимо заполнить поле id, а т.к. в таблице поле id не auto_increment - приходится извращаться
НЛО прилетело и опубликовало эту надпись здесь
>=0 - это смайл.
нет, не об этом
вот Вам одной строчкой (но длинной).
function getNewId( $tableName, $idFieldName ){ return $conn -> selectrow_arrayref("SELECT ( MAX($idFieldName) OR 0 ) + 1 FROM $tableName"); }

работоспособность не гарантирую, да и врядли кому это понадобится...
PS: улыбнуло)
в таком виде у вас $conn в функции не будет существовать :)
Скорее всего, автор имел в виду не национальность автора опубликованного фрагмента, а его духовные корни. :)
НЛО прилетело и опубликовало эту надпись здесь
Ну не одной строчкой, а SQL запрос вроде один будет, который и будет ID возвращать. Написать, не напишу, потому что навскидку не вспомню.
MySQL-ный INSERT вернёт ID.
сам по себе insert никуда ничего не возвращает
НЛО прилетело и опубликовало эту надпись здесь
Не всегда программист имеет возможность вот так просто работать с БД. Часто для этого приходится теребить админов, а это может занять некоторое время. Я, конечно, согласен, что регистрация на сайте — это дело важное, и при проектировании структуры базы данных нельзя делать таких ошибок, а раз уж они совершены, то исправлять их надо самым правильным образом. Так что программиста этого скрипта я ничуть не оправдываю, но сам подход вычисления нового id как (max(id) + 1) может быть иногда оправдан.
НЛО прилетело и опубликовало эту надпись здесь
mysql_query('ALTER ...
А если у пользователя базы права SELECT, INSERT, UPDATE?
фантазировать можно до бесконечности, но это уже совсем фантастика: чтобы админ оказался одновременно умным для ограничения прав на мускуль и тупым, чтобы не дать девелоперу нормальных прав, плюс настолько недоступным, что для девелопера оказалось проще написать свою имплементацию прекрасно работающего авто_инкремента

учитывая то, что реализован-то этот костыль и то криво, можно с 99% вероятностью утверждать, что девелоперу просто неведом автоинкремент
Мне кажется, что программист (или архитектор приложения) должен сам разрабатывать структуру БД и затем передавать ее админам на внедрение и сопровождение.
НЛО прилетело и опубликовало эту надпись здесь
Получение айдишника тупо сделали
НЛО прилетело и опубликовало эту надпись здесь
Смотря когда это было. Думаю да, сравнительно тупого были... но не настолько... я постоянно даю код на оценки и такие вещи находили :)

У меня тупость была скорее в неоптимальности кода, а тут действительно тупость :)
Помню у меня была такая-же проблемма (нужно было получить айди след записи). Потратил тогда 3 часа, перебрал все возможности и выбрал mysql_insert_id :) Но потом понял что это всё херня и переписал код так, чтобы айдишник вообще был ненужен )
масс ошибки, пойду спать, mozg offline ^^
НЛО прилетело и опубликовало эту надпись здесь
гы) Ну я у индусов код тоже ужасный видел.

Кстати это видимо показатели счётчика посещений))) лучше бы они туда рандом пихнули. Видимо им проще каждый день вручную приписывать)))
>>P.S. Программист индус

Чем вам индусы не нравятся? Такой "код" может написать любой, вне зависимости от его национальности.
Я разве где-то написал, что мне не нравятся индусы? Я просто констатировал факт
Ну, просто это отделено в конце, и бросается в глаза.
Они, видимо, заслужили попасть под такой стереотип...
Вааще-то здесь проблема не в том как это делать (mysql_insert_id не поможет), а в том, что этого делать вааще не надо.

Индусы они смешные :)
Мда. Индусы пишут много и криво. Но все же это работает. Иногда даже говорят - хорошо написано то, что работает...
Сразу вспоминаю:

if ($flag == false) {
# на вский случай
if (false == true)
exit;
include "execute.php";

или проверку булевых значений:

if (b.ToString().length < 5){...}
В том-то и проблема, что это работает пока тестируешь на локальной машине и при маленьком потоке пользователей. А потом время от времени будет ломаться, чем больше нагрузка тем чаще.
Все из-за того, что среда многопользовательская и может придти два запроса с маленькой разницей по времени и будет конфликт ID.
if (false == true)
exit;
Защищает от подъебов в стиле #define true false
т.к. речь о php - это бесмысленная проверка. попробуйте переопределить)
Могу предположить, что код нужен. Для систем с возможностью удаления пользователей это гарантирует, что у нового пользователя не будет ID от какого-нить старого.
Соответственно следы в базе, относящиеся к старому ID не навредят новому пользователю.

Автоинкремент не гарантирует постоянное увеличение.

Хотя в любом случае - это защита от того, что надо самому же в базе подчищать или обходить иначе.
как это? автоинкремент именно это и гарантирует :)
Если ничего не поменяли, то при переходе максимально возможного ID он пойдёт заполнять "дырки", начиная с 0. И кажется я видел, что было, что и не обязательно после перехода максимума...
испугался, ибо кое-где на это завязывался. Сделал тест:
CREATE TABLE test (id tinyint NOT NULL auto_increment, PRIMARY KEY(id))

потом зафигачил туда 255 записей, у последней, разумеется. id=255

фигачу следующую: Duplicate entry '255' for key 1 in query: INSERT INTO test () VALUES ()

удалил пару строчек из середины, результат - тот же.

так что не заполняет он дырки.
ах да, движок InnoDB
и tinyint был unsigned :)
Значит пофиксили. Я это видел в 3.дремучем мускуле или раньше.
А установить счетчик на таблице вручную что даёт?
если на отсутствующий ID - вставляет, пока не наткнется на существующий. И все, дальше не пойдет, т.к. не может вставить
Хочу заметить, что у InnoDB значение для автоинкремента генерируется при старте БД. То есть при старте базы данных выполняется поиск максимального значения поля.
А попробуйте удалить последнюю запись и добавить новую - она получит номер уже удаленной! Это тоже неправильно, т.к. может нарушить сслочную логику.
точно :)
с другой стороны, ситуация переполненного типа сама по себе ошибочная.
Ну да :)
Но с переполнением проще бороться - можно установить integer или bigint - тогда переполнения придется долго ждать :)
Ссылочную логику нужно другими средствами беречь.
Это внутри базы, а за ее пределами?
Сейчас как раз разрабатываю систему синхронизации данных с партнерами. Недавно один объект стал лишним, его удалили, и партнеры предложили создать новый с тем же id - чтобы дырку заполнить.
Чуть не убил на месте! Битый час объяснял почему нельзя так делать!
Представьте, на первый объект накопилась информация, а дальше инфа начинает поступать для другого, но вы об этом еще не знаете. Что в итоге? Полный бред вместо информации.
Нельзя ничего вставлять в таблицу, если мы удалили запись и остались ссылки на эту запись. Ибо целостность нарушена.
В таких случаях помогает правильная проектировка базы, с ON DELETE CASCADE http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html - система сама удалит все ссылающиеся записи.
Все так. Внутри базы мы можем контролировать, но после того как система разрастется и ее надо будет интегрировать с другими системами, начнутся проблемы.
Представьте, что в других системах есть ссылки на ваши объекты (неважно какие http, по id или еще как-то). Затем объект был удален и вместо него добавлен новый с тем же id. Внешняя система начинает работать с этим объектом - вот отличный источник «веселых» ошибок.
Автоинкремент как раз гарантирует постоянное увеличение. в MyISAM БД точно.
походу я зажрался в оракле со всякими там сиквенсами...
Да, тоже хотел предложить. Но зажрался таки постгресом )
Вот меня как раз стал тут интересовать вопрос сиквенсов, не подскажите где об этом можно хорошо почитать?
автор и с наличием секвенций в субд написал бы так же %)
вот вы пишете про фиговый код, написали бы правильный вариант, чтобы новичкам понятно было, как не следует делать...
эх... были врермена писал что-то вроде этого опуса :)) стыдно :)) Но с чего-то нужно начинать. Человек просто не знает об autoincrement :)
он есть не везде, посмотрите на тот же sqlite2, в sqlite3 чтоб сделать автоинкремент и то надо поплясать с бубном
извиняюсь, только ща увидел что юзается именно mysql_query :)
Я программер. В коде вижу косяк с >=0
Других моментов, которых можно назвать косяками - не вижу. Все остальное может быть объяснено.
Автор, плиз, скажи, а где здесь бред?
Напиши код, который не использует автоинкримент (по разным причинам это может быть нужно), как-то отработает в случае, если в запросе вывалится в исключение (нет таблицы, прав или соединения с базой данных), если запрос вернет пустое количество строк или действительно вернет значение.
Может в PHP есть это все одной командой?
Я вижу 2 косяка:
1) при большом кол-ве запросов возникнут глюки вставки, когда второй запрос придет между взятием max и записью max+1 в базу
2) при удалении последней записи нарушается ссылочная целостность.

Честно говоря, я ни разу не сталкивался с ситуацией, когда нельзя было использовать автоинкрементое поле. И всегда это было самое надежное решение. Поделитесь, пожалуйста, информацией когда оно не подходит.
Поддерживаю!
Если есть какие-то сложности можно сделать в БД таблицу со счетчиками и увеличивать ее используя update. Написать хранимку в конце концов. Или триггер. ;-) Сейчас пятый мускуль уже не редкость.
Нужно помнить, что в innodb значение автоинкремента вычисляется при каждом запуске сервера БД. И после удаления последних записей из таблицы с последующим рестартом сервера опять же можем получить нарушение ссылочной целостности.
Как вариант, но, думаю, тут придется лочить таблицу или использовать транзакции, чтобы избежать все той же проблемы с двойной вставкой.
Насчет поведения автоинкрмента в innodb не знал (последнее время чаще работаю с другой БД). Это всегда так? Или можно как-то этого избежать?
Судя по всему никак.
http://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html#innodb-auto-increment-traditional
Вот здесь вот подробно написано как это работает.
Я вот видел такую. Программа требовала заполнения других таблиц с ссылками на эту запись до добавления самой записи. Хотя это скорее ошибка проектирования.
+1
то что работает - написано правильно (до тех пор, пока не перестанет работать)
Единственное, что надо ответственно относиться к проектированию БД и кода, а то потом поддерживать зае...шся
В очередной раз заставило взгрустнуть о том, когда же наконец в mysql сделают sequence
Кароч. Единственное, что ясно из этого, что автор кода не читал доки по мускулу до конца и не задумывался, что перед созданием базы надо хотя бы продумать ее структуру, спросить бывалых.

ЗЫ: В данном случае автоинкремент решает все проблемы.
Еще было бы интересно увидеть каким образом индус использует эту функцию. Может там какой медитативный код, с предсказанием ID пользователя, который еще не зарегистрировался :-)
Только-только у себя написал про аналогичное. Афтар моего опуса - итальянец.
При использовании LINQ to SQL в .Net, при добавлении объекта пользователя в базу, id заполнится сам.
Dim newUser = New User() With {.Name = "Name"}
db.Users.InsertOnSubmit(newUser)
db.SubmitChanges()
return newUser.id
А ведь мог взять все записи, написать функцию сортировки массива, и взять последний элемент ;)
Кстати - подход с MAX(id) идеален для возрастающих ID, где выпады критичны. auto_increment при удалении последней записи не уменьшается.

а в остальном - wtf))
где могут быть критичны "выпады"?
ремарка: субд реляционная
вполне возможны, когда требуется строгий порядок ID, в ТЗ всё бывает

причем это логично только в том случае, если удаляются последнии записи, а не в середине.
>> в ТЗ всё бывает
да уж... ТЗ должно регламентировать результат, а не реализацию

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

ps: "порядковый номер" записи в mysql можно получить и без "залатывания окон" автоинкремента, хотя и это - тоже очень странное желание :-)

впрочем, не хотите рассказывать, не надо :-Р
"кто как играет..."
Подскажите вот здесь ..$record[0]+1.. "+1" зачем? Нехватает фантазии? )
мой мозг
какие каменты
бл%дь
бл%дь
бл%дь
ребята
это
жесточайший
пи%дец
может, вы ещё и минусуете топик, потому что не можете понять, где тут бред?
Ааа... я прослезился. Когда стажером писал программку в MS Access, приблизительно так же регистрировал новые записи фильмов и компаний в БД. Зато работало! :)

Жалко ее код я уже давно потерял, сейчас было бы ржачно наверно.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории