Apocaliptica61
Apocaliptica61

Reputation: 95

Generate a unique alphanumeric ID

My idea is to generate a unique ID for my table Alphanumeric for My table in SQL server So I use Newid function to do that and then I truncate the result to 8 character. My question is with this code I am sure to have a unique ID? Or maybe not here is the code:

DECLARE @r varchar(8) 

SELECT @r = coalesce(@r, '') + n 
FROM (SELECT top 8 CHAR(number) n 
   FROM master..spt_values 
   WHERE type = 'P' AND 
      (number between ascii(0) and ascii(9) 
         OR number between ascii('A') and ascii('Z') 
         OR number between ascii('a') and ascii('z')) 
   ORDER BY newid()) a 

DECLARE @id varchar(10)  
SET @id=CONVERT(varchar(8), @r)  
DECLARE @myid varchar(10) 

SELECT @myid=SUBSTRING(@r,1,2)+'-'+SUBSTRING(@r,3,3)+'-'+SUBSTRING(@r,6,3)  

PRINT 'Value of @myid is: '+ @myid

Upvotes: 2

Views: 12250

Answers (4)

nikyst
nikyst

Reputation: 1

create or replace FUNCTION "GEN1_9A_Z" ( start_val varchar2)
   return varchar2
-----------------------------------------------------------------------------------------------------------   
-----------------------------------------------------------------------------------------------------------
-- GEN1_9A_Z generate next unique alphanumeric string with size 3 -- (0..9A..Z) --
                -- Return 0 when error or end (ZZZ). --
-----------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------
-- 001,002,..,009,00A,00B,..,00Z,
-- 010,011,..,019,01A,01B,..,01Z,
-- .............................
-- 090,091,..,099,09A,09B,..,09Z,
-- 0A0,0A1,.................,0AZ,
-- 0B0,0B1,.................,0BZ,
-- .............................
-- 0Z0,0Z1,.................,0ZZ,
-- 100,101,.................,10Z,
-- 110,111,.................,11Z,
-- .............................
-- 990,991,.................,99Z,
-- 9A0,9A1,.................,9AZ,
-- .............................
-- 9Z0,9Z1,.................,9ZZ,
-- A00,A01,.................,A0Z,
-- A10,A11,.................,A1Z,
-- .............................
-- A90,A91,.................,A9Z,
-- AA0,AA1,.................,AAZ,
-- AB0,AB1,.................,ABZ,
-- ..............................
-- AZ0,AZ1,.................,AZZ,
-- B00,B01,.................,B0Z,
-- ..............................
-- ..............................
-- ZZ0,ZZ1,.................,ZZZ ---- END!!!

------------------------- generate 46656 unique alphanumeric. ( 000 - ZZZ ) --------------------------------
-----------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------
is 
   start_value varchar2(3);
   return_val  varchar2(3);
begin

if length(start_val) <= 3 then

  start_value := lpad(upper(start_val),3,'0');

  select 
  (case 
    when p1= 0 and p2 = 0 and p3 = 0 and v3 != '9'                                 then lpad(to_char(start_value+1),3,'0') 
    when p1= 0 and p2 = 0 and p3 = 0 and v3  = '9'                                 then v1||v2||chr(65) 
    when p1= 0 and p2 = 0 and p3 = 1 and ASCII(v3) between 65 and 89               then v1||v2||chr(ASCII(v3)+1)
    when p1= 0 and p2 = 0 and p3 = 1 and v2 != '9' and v3 = 'Z'                    then v1||chr(ASCII(v2)+1)||'0'
    when p1= 0 and p2 = 0 and p3 = 1 and v2  = '9' and v3 = 'Z'                    then v1||chr(65)||'0'
    when p1= 0 and p2 = 1 and p3 = 0 and v3 != '9'                                 then v1||v2||chr(ASCII(v3)+1)
    when p1= 0 and p2 = 1 and p3 = 0 and v3  = '9'                                 then v1||v2||chr(65)
    when p1= 0 and p2 = 1 and p3 = 1 and v3 != 'Z'                                 then v1||v2||chr(ASCII(v3)+1)
    when p1= 0 and p2 = 1 and p3 = 1 and ASCII(v2) between 65 and 89  and v3 = 'Z' then v1||chr(ASCII(v2)+1)||'0'
    when p1= 0 and p2 = 1 and p3 = 1 and v1 != '9' and v2 = 'Z' and v3 = 'Z'       then chr(ASCII(v1)+1)||'0'||'0'
    when p1= 0 and p2 = 1 and p3 = 1 and v1  = '9' and v2 = 'Z' and v3 = 'Z'       then chr(65)||'00'
    when p1= 1 and p2 = 0 and p3 = 0 and v3 != '9'                                 then v1||v2||chr(ASCII(v3)+1)
    when p1= 1 and p2 = 0 and p3 = 0 and v3  = '9'                                 then v1||v2||chr(65)
    when p1= 1 and p2 = 0 and p3 = 1 and v3 != 'Z'                                 then v1||v2||chr(ASCII(v3)+1)
    when p1= 1 and p2 = 0 and p3 = 1 and v2 != '9' and v3 = 'Z'                    then v1||chr(ASCII(v2)+1)||'0'
    when p1= 1 and p2 = 0 and p3 = 1 and v2  = '9' and v3 = 'Z'                    then v1||chr(65)||'0'
    when p1= 1 and p2 = 1 and p3 = 0 and v3 != '9'                                 then v1||v2||chr(ASCII(v3)+1)
    when p1= 1 and p2 = 1 and p3 = 0 and v3  = '9'                                 then v1||v2||chr(65) 
    when p1= 1 and p2 = 1 and p3 = 1 and v3 != 'Z'                                 then v1||v2||chr(ASCII(v3)+1)
    when p1= 1 and p2 = 1 and p3 = 1 and v2 != 'Z' and v3 = 'Z'                    then v1||chr(ASCII(v2)+1)||'0' 
    when p1= 1 and p2 = 1 and p3 = 1 and v1 != 'Z' and v2 = 'Z' and v3 = 'Z'       then chr(ASCII(v1)+1)||'00'  
    else '0' 
  end)
  into return_val
  from 
      (
      select 
       NVL(LENGTH(TRIM(TRANSLATE(substr(start_value,1,1), ' +-.0123456789',' '))),0) p1,
       NVL(LENGTH(TRIM(TRANSLATE(substr(start_value,2,1), ' +-.0123456789',' '))),0) p2,
       NVL(LENGTH(TRIM(TRANSLATE(substr(start_value,3,1), ' +-.0123456789',' '))),0) p3,
       NVL(substr(start_value,1,1),0) v1,
       NVL(substr(start_value,2,1),0) v2,
       NVL(substr(start_value,3,1),0) v3,
       start_value
        from  dual
  );
else 
    return_val := '0';
end if;
return return_val;
end;

Upvotes: 0

GilM
GilM

Reputation: 3761

I think this is a bad idea, and you'll have problems inserting more than one row at a time and maintaining unique values. But, just for fun, here's some code to increment a string with 8 alphanumeric characters (assuming values should run from 0-9, then A-Z):

DECLARE @s varchar(20)= '00-0Z-0Z-ZZ'; --INPUT
DECLARE @n char(36) = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
DECLARE @pos tinyint;
SET @s = REPLACE(@s,'-',''); --REMOVE DASHES
SET @pos = LEN(@s);
WHILE @pos > 0
BEGIN
    IF SUBSTRING(@s,@pos,1) = 'Z'
    BEGIN
        SET @s = STUFF(@s,@pos,1,'0');
        SET @pos = @pos - 1;
    END
    ELSE
    BEGIN
        SET @s = STUFF(@s,@pos,1,SUBSTRING(@n,
                                CHARINDEX(SUBSTRING(@s,@pos,1),@n)+1,1))
        SET @pos = 0
    END

END
SET @s =  SUBSTRING(@s,1,2) + '-' 
        + SUBSTRING(@s,3,2) + '-' 
        + SUBSTRING(@s,5,2) + '-' 
        + SUBSTRING(@s,7,2) -- Replace Dashes

SELECT @s --OUTPUT

Upvotes: 1

KeithS
KeithS

Reputation: 71565

NEWID() produces a v4 GUID. In that GUID scheme, the first 8 bytes can be any hexadecimal digit 0-F and will be composed entirely of randomly-generated data. That's not guaranteed to be unique; in fact no v4 GUID is guaranteed to be unique, it's just that the random bits (112 of 128) can represent one of 5.19 decillion numbers, so the odds of any two of them matching in the same system is infinitesimal. With only the first 8 bytes, you'll only have 2^32 combinations, which may still seem like a lot (1 in 4 billion) but by the birthday problem, after a scant 77,000 have been generated you have a 50-50 shot at generating a duplicate.

Upvotes: 4

Don Roby
Don Roby

Reputation: 41127

If I understand it correctly, SQL server's NewId generates a GUID (Globally unique identifier), which is a 128-bit value commonly presented as a 32-character hexadecimal string.

Being finite, it certainly can't guarantee uniqueness, as there are only 2^128 possible values. But that's a large enough space that collisions are rare.

If you truncate it to 8 characters (I'm assuming you mean 8 characters in the hexadecimal representation), you reduce the likelyhood of uniqueness greatly, as there are 2^32 possible values.

Uniqueness is certainly not guaranteed.

Upvotes: 0

Related Questions