2013-04-28 2 views
1

Я пытаюсь создать коды купонов для предоставления скидок. Я пробовал с Math.Random(), но я не уверен, будет ли он каждый раз обеспечивать уникальный код?Как сгенерировать уникальный код купе?

Также я пробовал использовать утилиту dbms_random.string «Oracle», которая генерирует случайные числа, но также не гарантирует уникальный код.

Кто-нибудь знает хороший алгоритм для этого?

Я использую java и oracle для разработки кода.

EDIT: После нескольких ответов я хотел бы добавить, что я должен хранить каждый сгенерированный код в таблице. И сгенерированный код должен быть буквенно-цифровым.

+0

код купона хранится в db? – Lokesh

+3

не может просто создать последовательность и использовать порядковый номер в качестве кода купона? – Lokesh

+0

@loki: Мне нужно сгенерировать коды купе с последовательностями, которые можно легко угадать. Поэтому любой может попробовать со следующим номером и пропустить коды купонов. Последовательность не является решением. –

ответ

1

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

Вам необходимо будет хранить где-нибудь (например, обратно в своей базе данных) коды, которые были использованы, а затем сканировать записи при создании нового кода.

Реально, вы можете создать 100 (или 1000 или 10000) купонов, хранить их и назначать их по мере необходимости.

+0

Первое, что я делаю в кодах в таблице, но перепрограммирование существующего кода не превалирует вообще, потому что мы должны генерировать купе в пакетах. –

3

Вы можете использовать Java UUID class. Он генерирует случайные 128-битовые буквенно-цифровые строки. Возможность повторения струны астрономически низка.

В частности:

import java.util.UUID 
. 
. 
String uniqueString = UUID.randomUUID().toString() 
. 
. 
+0

Не знаете, почему это не принято. UUID генерирует что-то вроде 32 буквенно-цифровых значений, поэтому вероятность столкновения равна (1/(26 (буквы) + 10 (числа))^(32))^2 = (1/(36^32))^2. ... вы никогда не столкнетесь. –

+1

Уникальный? Безусловно.В зависимости от того, находится ли это в магазине или он-лайн (где copy/paste - опция), может быть немного длиннее ввести код купона. – phatfingers

1

Я хотел бы объединить случайные числа + порядковый номер. Это дает вам случайное число, которое уникально, потому что порядковый номер уникален.

В противном случае вам необходимо выполнить пробный и ошибочный подход. Может быть, заранее, чтобы сохранить время выполнения. Предположим, у вас есть таблица «coupon-keys» с уникальным индексом coupon_id. Вы генерируете случайный ключ, а затем вставляете его. Вы поймаете неудачу вставки, если не уникальны, и повторите попытку, пока не получите достаточное количество ключей купона. Кроме того, у вас есть столбец «используется», и каждый раз, когда вы выдаете купон, вы обновляете столбец, чтобы отслеживать, какие номера купонов по-прежнему доступны.

+0

Это не гарантирует уникальность. Например, случайные числа 1234, 1233, выпущенные в последовательности 10051, 10052, будут сталкиваться (11285 == 11285). Если вы хотите преобразовать их в строки и объединить, то «123» + «456» могут столкнуться с «12» + «3456». – phatfingers

+0

Первый метод не гарантирует уникальность, но я думаю, что второй будет работать нормально. – phatfingers

+0

Да, я имел в виду нечто вроде фиксированной длины случайных чисел, оставшихся заполненными нулями, конкатенированными. Но на самом деле это просто быстрый трюк. Теперь, после одного дня ответа на это, я должен признать, что я думаю, что решение, которое мне лично больше всего понравилось, - это генерировать и вставлять повтор, если метод неудачных циклов. Если случайное число достаточно велико, это не должно быть так много испытаний. – hol

0

Вот мои предложения:

Ваша таблица должна выглядеть как

CREATE TABLE COUPONS 
    (COUPON_CODE NUMBER 
    CONSTRAINT PK_COUPONS 
     PRIMARY KEY 
     USING INDEX);  -- plus whatever other fields you need 

Ваш код, чтобы генерировать уникальные коды должны быть что-то вроде

DECLARE 
    nCoupon_code NUMBER; 
    bCode_unique  BOOLEAN; 
BEGIN 
    bCode_unique := FALSE; 

    WHILE bCode_unique = FALSE LOOP 
    BEGIN 
     nCoupon_code := GENERATE_COUPON_CODE; -- function to generate a coupon code 

     INSERT INTO COUPONS (COUPON_CODE) 
     VALUES (nCoupon_code); 

     bCode_unique := TRUE; 
    EXCEPTION 
     WHEN DUP_VAL_ON_INDEX THEN 
     NULL; -- Fall through, loop back to the top, generate new code, continue 
    END; 
    END LOOP; -- bCode_unique 
END; 

Что здесь является то, что программа сначала установите флаг «code unique» в FALSE, указывая, что уникальный код еще не создан. Затем вводится цикл и будет продолжаться до тех пор, пока флаг «code unique» по-прежнему будет FALSE. Затем генерируется и сохраняется код купона в базе данных. Если код уникален, все будет хорошо, будет установлен флаг «уникальный код», и цикл будет завершен. ОДНАКО, если код НЕ уникален, инструкция INSERT терпит неудачу с исключением DUP_VAL_ON_INDEX. Это произойдет потому, что COUPON_CODE является основным ключом в таблице COUPONS, и мы знаем, что первичный ключ имеет три атрибута: он должен быть не-NULL, если он никогда не должен изменяться, и он ДОЛЖЕН БЫТЬ УНИКАЛЬНЫМ. (Для наших целей здесь мы могли бы использовать ограничение UNIQUE для COUPONS.COUPON_CODE и получили тот же эффект).Если исключается исключение DUP_VAL_ON_INDEX, потому что генерируемый код купона не уникален, обработчик исключений будет введен, где код ничего не сделает; то есть флаг «code unique» останется FALSE, код будет выпадать из обработчика исключений, а поскольку флаг «уникальный код» по-прежнему FALSE, цикл начнется снова, когда будет сгенерирован другой код, и т. д. etc и т. д., пока не будет создан уникальный код и INSERT удастся.

Это может показаться большой работой, но если алгоритм генерации кода купона выбран хорошо, он не будет генерировать много столкновений и, следовательно, не будет слишком часто чередоваться. ИМО это разумное решение с учетом окружающей среды - в PL/SQL вы рассчитываете использовать базу данных для выполнения некоторых тяжелых операций, таких как гарантия уникальности. Вы можете потратить много времени, пытаясь придумать алгоритм генерации одного True кода, который никогда не будет когда-либо генерировать дубликат, или вы можете просто придумать что-то хорошее, если не совершенное и работать с базой данных, чтобы убедитесь, что коды, которые окончательно выбраны, становятся уникальными. YMMV. И реализация One True Algorithm может быть очень забавной, если не особенно хорошо использовать время. :-)

Делитесь и наслаждайтесь.

0

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

String chars[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); 

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

int max=100000000; 
int random=(int) (Math.random()*max); 
StringBuffer sb=new StringBuffer(); 
while (random>0) { 
    sb.append(chars[random % chars.length]); 
    random /= chars.length; 
} 
String couponCode=sb.toString(); 

Итак, сгенерируйте случайное число, сократите его до строки и вставьте в свою базу данных. Если вставка не удалась из-за столкновения, повторите попытку. Столкновения должны быть довольно редкими, и они будут иметь минимальную стоимость, когда они произойдут. Ваши коды купонов должны оставаться короткими и легкими для ввода.

1

Oracle от 10g up имеет пакет dbms_crypto, включенный для генерации подлинно случайных последовательностей.

http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_crypto.htm#i1000605.

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

http://psoug.org/reference/utl_encode.html

Если купонные коды достаточно долго, столкновения должны быть неосуществимым, но вы могли бы еще обернуть создание купона в функции PL/SQL для обработки любых столкновений. Например. используйте ограничение UNIQUE и поймайте исключение, если INSERT завершится с ошибкой. (Как предложил Боб Джарвис.)

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