Как выбрать случайный и уникальный ID в mysql

Статус
В этой теме нельзя размещать новые ответы.

verfaa

Профессор
Регистрация
29 Янв 2007
Сообщения
416
Реакции
49
В таблице есть поле orders_id
в нём хранятся числовые id заказов в таком виде:

29
457
3467844
235
2345
33467899
331136
9272

Т.е. случайные числа не по-порядку.
Каким образом (с помощью запроса mysql) можно сгенерировать случайное число в диапазоне 10-10000000, которого НЕТ в поле (т.е. уникальное для этого поля)?
 
Как вариант - отсортировать по возрастанию и добавить еденицу к последнему значению
 
Это тоже не вариант, если максимальное значение окажется слишком большим, скажем 10 млн. будет не совсем удобно с ним работать.

Мне тут настойчиво советуют auto_increment, поэтому дополню свой вопрос:
Когда пользователь переходит на страницу заказа я должен сгенерировать уникальный ID заказа и вписать его в скрытое поле <input type='hidden' name='ornum' value='265895' /> на странице заказа.

Этот ID я передаю биллингу, когда пользователь кликает "оплатить" и попадает на сайт биллинга.

На стадии оформления заказа биллинг передаёт мне этот ID обратно в скрытый файл Result.php и, если все успешно я вписываю этот ID к себе в БД MySQL вместе с другой информацией по платежу.

Теперь вопрос, если к примеру на сайте было 20 заказов, пользователь перешел на страницу заказа, я вписал в скрытое поле следующий незанятый ID - 21. В это время заказ начали оформлять ещё 5 пользователей - им тоже вписал скрытое поле ID - 21, ведь он ещё не занят (биллинг не обращался на Result.php и в БД этот ID не вписан). В результате я получу ситуацию когда в какой то момент пользователь оформлявший заказ, завершил его вписав ID 21 в БД. А следующий сразу за ним другой пользователь, тоже получивший ID 21 будет пытаться вписать в БД дублирующую запись и получит ошибку, если поле будет, как мне советуют auto_increment.
 
rand не решит полностью проблему с возможным дублированием (в лотереи ведь люди выигрывают :) )
тебе всё же стоит вести таблицу с auto_increment

Когда пользователь переходит на страницу заказа я должен сгенерировать уникальный ID заказа и вписать его в скрытое поле <input type='hidden' name='ornum' value='265895' /> на странице заказа.

Этот ID я передаю биллингу, когда пользователь кликает "оплатить" и попадает на сайт биллинга.

Между этими двумя пунктами твой обработчик на php? Если да создавай новый заказ с пометкой не оплачено и передавай биллингу id из таблицы.
 
rand не решит полностью проблему с возможным дублированием (в лотереи ведь люди выигрывают :) )
Можно использовать таки rand, но добавить на всякий пожарный проверку на уникальность сгенерированного ключа и перегенерить, если такой ключ уже есть.
Правда это дополнительный запрос в базу, а значит допнагрузка.
 
Создать переменную табличного типа, заполнить её в цикле нужным диапазоном, заджойнить с целевой таблицей левым соединением, исключить совпадающие и взять топ 1. Этот селект должнен быть значением для инсерта в целевую таблицу, иначе могут быть коллизии при больших нагрузках. А по уму лучше действительно инкремент использовать.
 
В таблице есть поле orders_id
в нём хранятся числовые id заказов в таком виде:

29
457
3467844
235
2345
33467899
331136
9272

Т.е. случайные числа не по-порядку.
Каким образом (с помощью запроса mysql) можно сгенерировать случайное число в диапазоне 10-10000000, которого НЕТ в поле (т.е. уникальное для этого поля)?
тоесть, нельзя взять и привести к нормальному виду заказы? сделать поле order_id_inc автоинкрементом и проапдейтить все связи, а потом переименовать в orders_id? правда, да, логику нужно будет чуток поправить. но это дело скажем одного дня, чем потом опять на грабли наступать (если таковые есть) и опять искать какието решения.

просто прикинуть, что в определённый момент будет 100500100500 очень много записей и процедура генерации айди будет всё медленнее и медленнее, это в случае если будете искать рендом которого ещё нет в базе
 
Можно использовать таки rand, но добавить на всякий пожарный проверку на уникальность сгенерированного ключа и перегенерить, если такой ключ уже есть.
Правда это дополнительный запрос в базу, а значит допнагрузка.

Генератор случайных чисел с последующей проверкой нельзя использовать. Есть ненулевая вероятность того, что подбор не закончится никогда. Да и с ростом количества значений в таблице время подбора будет увеличиваться.

Что это за магазин такой, где код заказа без авто_инкремента? Разве что это вопрос безопасности (типа чтоб нельзя было угадать код следующего заказ). Но мне кажется, что если б все было настолько серьезно, то ТС не просил бы помощи..
 
Если по сути топик-стартера, то тут явно кривой движек и нужен тупо инкремент.
А по поводу рандома - в свое время для купонного сервиса было придумано следующее решение - hex(xx...xxx.hh.dd.mm.yyyy.xx...xxx) + проверка на уникальность (xx...xx - это некий рандомный диапазон). При огромном числе оных совпадений не было ни 1. С числами можно то же самое сделать (хоть timestamp брать с довеском), просто очень большие величины.
 
Если по сути топик-стартера, то тут явно кривой движек и нужен тупо инкремент.
А по поводу рандома - в свое время для купонного сервиса было придумано следующее решение - hex(xx...xxx.hh.dd.mm.yyyy.xx...xxx) + проверка на уникальность (xx...xx - это некий рандомный диапазон). При огромном числе оных совпадений не было ни 1. С числами можно то же самое сделать (хоть timestamp брать с довеском), просто очень большие величины.


У вас хоть hex был, а у ТС целые числа. Повторюсь, при рандомном подборе с проверками существует НЕНУЛЕВАЯ вероятность того, что подбор будет вечным. Да, эта вероятность очень-очень низка, но тем не менее существует. На продакшне такого нельзя допускать. А вдруг заказ на миллион, а клиент сидит как баран и ждет.

Если действительно нужен элемент случайности - брать максимум и добавлять к нему rand(10), ну или rand(100), насколько позволит совесть и размерность поля в базе.

Но и это тоже на самом деле плохо. При сотне тысяч записей mysql'у надоест их сортировать. Да и хостер за такое по голове не погладит.

Лучшее решение - AUTO_INCREMENT в любом случае.
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху