Reputation: 1241
I'm using informix IDS server, and I have this table table1
:
Column name Type Nulls
ad_code char(5) yes
ad_value smallint yes
I would like to generate a random, unique code for field ad_code
(and then store it in the ad_code
field) of table table1
using sql.
Is it possible ?
It would be enough, alternatively, an alphanumeric code sequnziale, es. 00001 ... 00009 ... 0000A unique
I have tried something like this, in the case of hexadecimal values in the
field 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;
but is very slow despite having created an index on ad_code
.
Upvotes: 1
Views: 513
Reputation: 754480
You can generate 15-bit random numbers using this pair of stored procedures:
-- @(#)$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;
You can use those numbers to generate a sequence of alphanumeric characters, with more or less finesse. A simple approach uses the random number modulo the number of alphanumeric characters (do you want [A-Z0-9]
or [a-z0-9]
or [A-Za-z0-9]
, or something else), and select a character each time. There is potential for unequal distributions if you are not careful (because if there are 32768 possible random numbers, and you have 36 possible characters, 8 of characters will have a 911 out of 32768 chance of being selected, while the other 28 will only have a 910 out of 32768 chance of being selected (and the problem is bigger if you use 62 characters — lower-case, upper-case and digits). There are ways to deal with that if it is a problem.
Here's the simple-minded, slightly skewed approach at work:
-- @(#)$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);
Sample output:
087TTLGDMSNXMAFL7PJG
cklp14dfk66308lxkzjyu
6JDTOJLC47UE9GWSHRBH55
gwpmrfwwwcykgqbn494bmeh
TNY3U3VMHN01UZS1GV4LOF0K
tm38v8qwqj6o0vrsh9gbb0w6
YF6QP6NT3VK5ARTFDL1N32B
vrb9pvww5cw6egsz9tniex
9OIY799Z694DBENBDFSFE
1gkj5adm3bswlo26wd5i
I didn't set the seed, so that code generates the same sequence every time. You might use a sequence to generate a new seed each time, or you might do something else to seed the generator. The seed is private to each session.
Upvotes: 2