2011-12-14 3 views
0

Я генерирую случайную 10-значную строку с php и вставляя ее в столбец в моей БД. Моя проблема в том, что я хочу, чтобы эта строка была уникальной (в базе данных). Я думал о многих способах сделать это, но интересно, какой путь является наиболее эффективным.Уникальное значение в непервичном поле

Мой PHP выглядит следующим образом (случайная строка может быть только длиной 10 символов):

//generates an almost unique(not quite) ticket number 
$pretrimmedtask = md5(uniqid(mt_rand(),true)); 
$tasknum = substr($pretrimmedtask ,0,10); 

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

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

+0

Важно ли, чтобы идентификатор был хешем, а не числом? – TimWolla

+0

есть. Я бы предпочел, чтобы это был номер, но он должен быть хешем. – Kyle

+1

Вы можете установить ключ UNIQUE в поле tasknum и уловить ошибки из системы db во время запроса, повторно генерируя значение tasknum и повторно вставляя при возникновении столкновений имен. – rdlowrey

ответ

1

Вы должны обновить таблицу и сделать соответствующий столбец UNIQUE KEY, чем попытаться вставить сгенерированную строку, если строки не вставлены, сгенерировать другой ключ и повторить попытку.

ALTER TABLE table_name ADD UNIQUE KEY (column_name); 

Код ниже будет пытаться INSERT новой строки в table1, если невозможно будет повторить попытку с другим случайным образом генерируется $key.

IE. запрос не будет успешным, если col2 имеет уникальное ограничение ключа, а значение $key уже существует в столбце.

function generate_random_string() { 
    $charset = array_merge (
    range ('a', 'z'), range ('A','Z'), range ('0','0') 
); 

    shuffle ($charset); 

    return join ('', array_slice ($charset, 0, 9)); 
} 

/* ....................................................... */ 

do { 
    $key = generate_random_string(); 
} while (
    !mysql_query ("INSERT INTO table1 (col1,col2) VALUES (123, '$key')") 
); 

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

ПРИМЕЧАНИЕ: Убедитесь, что запрос может быть успешным, чтобы вы не попали в бесконечный цикл.

+0

oh man, я не использовал do, пока слишком долго , спасибо приятелю, работает как шарм. – Kyle

1

Создать уникальный индекс MySQL, который охватывает только это поле и вставка значение в цикле до достижения успеха.

Как:

while (true) { 
    $random = generate it; 
    try to insert; 
    if (inserted without errors) break; 
} 
0

ли он должен быть 10 символов. С помощью crypt() вы можете генерировать 13-символьные длинные хэши.

Здесь http://www.php.net/manual/en/function.hash.php вы можете проверить длину различных методов хэширования. Ни один из них, к сожалению, не производит ровно 10 символов длинной строки. Но вы можете сгенерировать строку длиной 8 символов и добавить два символа.

Другое возможное решение, с которым я столкнулся, - использовать текущую дату генерации строки. Unixtimestamp - это только цифры и длинные, но мы можем преобразовать дату в 10 строк символов следующим образом:

Создайте два массива, сначала с ключами от 1 до 31 и назначьте один символ для каждой клавиши (26 букв плюс 10 цифр сделают трюк), второй массив должен иметь ключи от 0 до 99 и иметь значения двух длинной строки charater.

Теперь возьмите день, месяц, год (2 цифры), час, минуту и ​​секунды текущего времени и замените значение значением из массива, где день и месяц берутся из первого массива, а остальное - из второй. Объедините это, и у вас есть уникальная строка длиной 10 символов.

+0

Не имеет значения, какую функцию хеширования использовать (или вообще не использовать), потому что вам все равно нужно генерировать базовые данные, которые будут хэшироваться. – zerkms

+0

Я понимаю, что результат должен быть длиной 10 символов, поэтому здесь используется метод хэширования. Базовые данные всегда могут быть time(), поскольку они различны каждый раз или md5 времени() или sha1 времени или md5 из sha1 времени() – Zefiryn

+0

Я хотел сказать, что нет никакой разницы между разрезанием первых 13 символов md5 или генерации 13-символьной длины склепа() – zerkms

0

Этот вопрос сам.

Я использую (insert) time() и insert/row id (+ специальный массив букв) md5-ed все вместе как одна строка и хэширование - для некоторых целей cookie позволяет сказать. Таким образом, этот ключ раскрывается.

Вставить (или строку) идентификатор нельзя дублировать и объединить с отметкой времени unix (10 цифр) + случайные буквы и md5-ed вместе создает, безусловно, уникальный «второй ключ», несколько сложнее сломать то, что доступно через файлы cookie. В этом случае его невозможно сломать.

Но это хэш.

Если 10 символов важны - поскольку я не могу найти причину, вы можете создать функцию для создания таких ключей, как (99999999999999999999-primary key) + substr 10 с включенными буквами, но это зависит от уровня экспозиции этого ключа.

Однако substr не является вариантом, а роль первичного ключа просто необходима.

Смежные вопросы