[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Поиск незанятого/несуществующего значения
glock18
Привет всем.

Ситуация такая:
есть таблица
SQL
create table user (
id int not null auto_increment,
alias varchar(80) not null,
code smallint not null,
primary key (id),
unique key (alias, code)
);

Алиас и код могут меняться во времени. Не слишком часто впрочем.
Задача состоит в том, чтобы найти случайное число для колонки code новой записи такое, что оно гарантированно не существует в базе данных для данного alias'а (очень желательно чтобы число было как минимум трехзначное в 16-ой системе исчисления).

Вот пример:
1 vasya-pupkin 0x3f90
2 vasya-pupkin 0x193e
3 vitya-petechkin 0x3813

Если регистрируется еще один Вася Пупкин, то ему нужно присвоить алиас vasya-pupkin и случайный код, не занятый прежде другими Васями Пупкиными.

Мои измышления пока привели к вариантам, которые мне очень не нравятся:
1. брать рандомное число и проверять есть ли оно в базе в цикле.
2. выбирать из таблицы все соответствующие коды и потом генерить рандомом число, не входящее в них.

2 вариант видимо получше, но в меня закралась надежда, что в mysql может быть какая-то встроенная фича, которая поможет разрулить эту ситуацию без дополнительных запросов.



Спустя 1 час, 52 минуты, 30 секунд (30.09.2009 - 12:03) Sylex написал(а):
glock18
а если взять еще большую разрядность? Тем самым просто исключая возможность совпадений

Спустя 7 минут, 18 секунд (30.09.2009 - 12:10) sergeiss написал(а):
Я чего думаю... Можно так сделать. Берем твой "вариант 2", только модифицируем его. Надо будет сделать скрипт, который запускается раз в день (месяц, неделю) или по необходимости.
1-й этап. Выбираем все незанятые числа, удовлетворяющие потребностям (например, твоё "как минимум трехзначное в 16-ой системе исчисления").
2-й этап. Перемешиваем их в произвольном порядке, и пишем в отдельную таблицу в БД. Получаем "псевдослучайную" последовательность чисел, не занятых другими людьми.
3-й этап. Когда есть потребность, достаем первое же число, и удаляем его из таблицы псевдослучайных. Один маленький запрос, выполнится очень быстро.
4-й этап. Если чисел становится слишком мало, то автоматически запускаем скрипт, который генерит эти числа.

Этапы 1-2 - это один несложный запрос smile.gif И не важно, сколько времени он будет выполняться, потому что пользователь не будет ждать его.

Спустя 3 минуты, 52 секунды (30.09.2009 - 12:14) Sylex написал(а):
md5(now())
wink.gif

Спустя 3 минуты, 53 секунды (30.09.2009 - 12:18) glock18 написал(а):
Sylex
большая разрядность вряд ли подойдет, увы. Да и совпадения, увы, не будут исключены.

А разрядность не подойдет по той причине, что алиас и код вместе будут в урле на страницу юзера.

типа
/home/vasya-pupkin
/home/vasya-pupkin/code/3f09

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

Спустя 2 минуты, 2 секунды (30.09.2009 - 12:20) glock18 написал(а):
sergeiss
Честно говоря, вряд ли подойдет. Как я говорил, код может вполне меняться. Юзер меняет свои имя и фамилию - получает новый алиас и новый код. Плюс код должен быть уникален для каждого алиаса, а не по всей таблице.

Спустя 6 часов, 10 минут, 47 секунд (30.09.2009 - 18:31) Sylex написал(а):
glock18

65535 вариантов это слишком дофига... сколько примерно предполагается записей может быть с одним алиасом? Может вероятность попадания очень мала? И можно не париться и генерить случайное число? smile.gif

А если че ON DUPLICTE KEY UPDATE .... new_key smile.gif

если не годится - тогда 1 вариант предложенный тобой

Спустя 23 минуты, 21 секунда (30.09.2009 - 18:54) glock18 написал(а):
Цитата
А если че ON DUPLICTE KEY UPDATE .... new_key

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

Ладно, спасибо, что откликнулись Sylex и sergeiss. буду размышлять теперь smile.gif

Спустя 2 часа, 14 минут, 20 секунд (30.09.2009 - 21:08) kirik написал(а):
glock18
Ну и от меня еще вариантик smile.gif
Похож на твой первый, только проверять не в цикле, а как-то так:
Свернутый текст
PHP
function generateCode()
{
    
// $code = генерируем рандомное число
    
return $code;
}


function 
getNewCode($alias)
{
    
$code generateCode();
    
$result mysql_query("SELECT `id` FROM `user` WHERE `alias` = '{$alias}' AND `code` = '{$code}'");
    if(
mysql_num_rows($result) > 0)
    {
        return 
getNewCode($alias);
    }
    else
    {
        
mysql_query("INSERT INTO `user` SET `alias` = '{$alias}', `code` = '{$code}'");
        return array(
'id' => mysql_insert_id(), 'code' => $code);
    }
}

print_r(getNewCode('vasya-pupkin'));

Либо можно его же оформить в mysql'ную функцию, чтобы не гонять запросы туда-сюда..
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2025 Invision Power Services, Inc.