Можно ли сгенерировать уникальный случайный буквенно-цифровой код, состоящий из 5 символов, используя Informix или стандартный sql? - PullRequest
0 голосов
/ 27 августа 2018

Я использую сервер informix IDS, и у меня есть эта таблица table1:

Column name          Type                                    Nulls

ad_code              char(5)                                 yes
ad_value             smallint                                yes

Я хотел бы сгенерировать случайный уникальный код для поля ad_code (и затем сохранить его в поле ad_code) таблицы table1 с помощью sql. Возможно ли это?

В качестве альтернативы было бы достаточно буквенно-цифрового кода sequnziale, es. 00001 ... 00009 ... 0000A уникальный

Я пробовал что-то подобное в случае шестнадцатеричных значений в поле ad_code:

select  first 5  ('0x'||NVL( l.ad_code, '0'))::INT + 1
from table1 as l
left outer join table1 as r on
('0x'||NVL( l.ad_code, '0'))::INT + 1 =
('0x'||NVL( r.ad_code, '0'))::INT
where       
r.ad_code is null ORDER BY 1 ASC;
commit;

, но очень медленно, несмотря на то, что создал индекс на ad_code.

1 Ответ

0 голосов
/ 27 августа 2018

Вы можете генерировать 15-битные случайные числа, используя эту пару хранимых процедур:

-- @(#)$Id: random.spl,v 1.2 1997/12/08 19:31:44 johnl Exp $
--
-- Simple emulation of SRAND and RAND in SPL
-- Using random number generator suggested by C standard (ISO 9899:1990)

CREATE PROCEDURE sp_setseed(n INTEGER)
        DEFINE GLOBAL seed DECIMAL(10) DEFAULT 1;
        LET seed = n;
END PROCEDURE;

CREATE PROCEDURE sp_random() RETURNING INTEGER;
        DEFINE GLOBAL seed DECIMAL(10) DEFAULT 1;
        DEFINE d DECIMAL(20,0);
        LET d = (seed * 1103515245) + 12345;
        -- MOD function does not handle 20-digit values...  Dammit!!
        LET seed = d - 4294967296 * TRUNC(d / 4294967296);
        RETURN MOD(TRUNC(seed / 65536), 32768);
END PROCEDURE;

Вы можете использовать эти числа, чтобы сгенерировать последовательность буквенно-цифровых символов, с более или менее утонченной точностью. Простой подход использует случайное число по модулю количества буквенно-цифровых символов (хотите ли вы [A-Z0-9] или [a-z0-9] или [A-Za-z0-9], или что-то еще) и выбираете символ каждый раз. Существует вероятность неравного распределения, если вы не будете осторожны (потому что, если есть 32768 возможных случайных чисел и у вас есть 36 возможных символов, 8 символов будут иметь 911 из 32768 шансов быть выбранными, в то время как остальные 28 будут иметь только 910 из 32768 шансов быть выбранными (и проблема больше, если вы используете 62 символа - строчные, прописные и цифры). Есть способы справиться с этим, если это проблема.

Вот простой, слегка искаженный подход на работе:

-- @(#)$Id: randomstring.spl,v 1.1 2018/08/27 16:43:59 jonathanleffler Exp $
--
-- Generate a random sequence of characters from given list

CREATE FUNCTION sp_randomstring(str VARCHAR(255), num INTEGER)
    RETURNING VARCHAR(255) AS random_string;
    DEFINE r VARCHAR(255);
    DEFINE i INTEGER;
    DEFINE n INTEGER;
    DEFINE j INTEGER;
    LET r = "";
    LET n = LENGTH(str);
    FOR i = 1 TO num
        LET j = MOD(sp_random(), n) + 1;
        LET r = r || SUBSTR(str, j, 1);
    END FOR;
    RETURN r;
END FUNCTION;

EXECUTE FUNCTION sp_randomstring("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 20);
EXECUTE FUNCTION sp_randomstring("abcdefghijklmnopqrstuvwxyz0123456789", 21);
EXECUTE FUNCTION sp_randomstring("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 22);
EXECUTE FUNCTION sp_randomstring("abcdefghijklmnopqrstuvwxyz0123456789", 23);
EXECUTE FUNCTION sp_randomstring("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 24);
EXECUTE FUNCTION sp_randomstring("abcdefghijklmnopqrstuvwxyz0123456789", 24);
EXECUTE FUNCTION sp_randomstring("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 23);
EXECUTE FUNCTION sp_randomstring("abcdefghijklmnopqrstuvwxyz0123456789", 22);
EXECUTE FUNCTION sp_randomstring("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 21);
EXECUTE FUNCTION sp_randomstring("abcdefghijklmnopqrstuvwxyz0123456789", 20);

Пример вывода:

087TTLGDMSNXMAFL7PJG
cklp14dfk66308lxkzjyu
6JDTOJLC47UE9GWSHRBH55
gwpmrfwwwcykgqbn494bmeh
TNY3U3VMHN01UZS1GV4LOF0K
tm38v8qwqj6o0vrsh9gbb0w6
YF6QP6NT3VK5ARTFDL1N32B
vrb9pvww5cw6egsz9tniex
9OIY799Z694DBENBDFSFE
1gkj5adm3bswlo26wd5i

Я не установил начальное значение, поэтому код генерирует одну и ту же последовательность каждый раз. Вы можете использовать последовательность для генерации нового начального числа каждый раз, или вы можете сделать что-то еще для начального заполнения генератора. Семя является частным для каждого сеанса.

...