2

我的想法是为我的表在 SQL 服务器中为我的表生成一个唯一的 ID,所以我使用 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

4 回答 4

4

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

于 2012-09-17T22:32:54.997 回答
1

我认为这是一个坏主意,一次插入多行并保持唯一值会遇到问题。但是,只是为了好玩,这里有一些代码可以用 8 个字母数字字符递增一个字符串(假设值应该从 0-9 运行,然后是 AZ):

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
于 2012-09-17T23:16:34.040 回答
0

如果我理解正确,SQL Server 的 NewId 会生成一个GUID(全局唯一标识符),它是一个 128 位值,通常以 32 个字符的十六进制字符串表示。

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

如果将其截断为 8 个字符(我假设您的意思是十六进制表示中的 8 个字符),则会大大降低唯一性的可能性,因为有 2^32 个可能的值。

当然不能保证唯一性。

于 2012-09-17T22:31:03.097 回答
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;
于 2014-08-08T07:28:49.743 回答