2

私の考えは、テーブルの一意の ID を SQL サーバーのテーブルの英数字で生成することです。そのため、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()はv4GUIDを生成します。そのGUIDスキームでは、最初の8バイトは任意の16進数の0〜Fであり、完全にランダムに生成されたデータで構成されます。これが一意であるとは限りません。実際、v4 GUIDが一意であることが保証されているわけではなく、ランダムビット(128の112)が5.19デシリオンの数値のいずれかを表すことができるため、同じシステムで一致する2つの数字のオッズはごくわずかです。最初の8バイトだけでは、2 ^ 32の組み合わせしかありません。これはまだ多くのように見えるかもしれませんが(40億分の1)、誕生日の問題により、わずか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サーバーのNewIdはGUID(グローバル一意識別子)を生成します。これは、通常32文字の16進文字列として表される128ビット値です。

可能な値は2^128しかないため、有限であるため、一意性を保証することはできません。しかし、それは衝突がまれであるのに十分な大きさのスペースです。

これを8文字に切り捨てると(16進表現では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 に答える