生成唯一的字母数字ID

时间:2012-09-17 22:15:19

标签: sql sql-server tsql

我的想法是在SQL服务器中为我的表生成一个唯一的ID Alphanumeric for My table所以我使用Newid函数来执行此操作,然后将结果截断为8个字符。我的问题是这个代码我肯定有一个唯一的ID?或者可能不是这里的代码:

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

4 个答案:

答案 0 :(得分:4)

NEWID()生成v4 GUID。在该GUID方案中,前8个字节可以是任何十六进制数字0-F,并且将完全由随机生成的数据组成。这不能保证是独一无二的;实际上没有保证v4 GUID是唯一的,只是随机位(128个中的112个)可以代表5.19 十亿个数字中的一个,因此它们中的任何两个匹配在同一系统中的几率是无穷小的。只有前8个字节,你将只有2 ^ 32个组合,这可能看起来仍然很多(四十亿分之一)但是由于生日问题,在生成了少量77,000之后你有50-50个镜头在生成副本。

答案 1 :(得分:1)

我认为这是一个坏主意,你一次插入多行并保持唯一值会有问题。但是,只是为了好玩,这里有一些代码来增加一个包含8个字母数字字符的字符串(假设值应该从0-9开始,然后是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

答案 2 :(得分:0)

如果我理解正确,SQL服务器的NewId会生成GUID (Globally unique identifier),这是一个128位的值,通常表示为32个字符的十六进制字符串。

有限,它肯定不能保证唯一性,因为只有 2 ^ 128个可能的值。但这是一个足够大的空间,碰撞很少见。

如果你把它截断为8个字符(我假设你的意思是十六进制表示中的8个字符),你可以大大减少唯一性的可能性,因为有2 ^ 32个可能的值。

当然不能保证唯一性。

答案 3 :(得分:0)

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;