2017-08-04 79 views
2

我使用下面的函數來生成5個字母的隨機密鑰,但它是所有字母和數字的組合。使用SQL Server的隨機密鑰生成

但按照要求,我需要生成一個不包含字符'o'和'我',也不包含數字'0'和'1'的隨機唯一鍵。

DECLARE @automateKey VARCHAR(15) 
    DECLARE @Length INT = 6 
    DECLARE @Count INT = 2 

    SET @Length = @Length + 1 
    SET @Count = @Count + 1 

    SELECT @automateKey = 
      (SELECT CAST((ABS(Checksum(NewId())) % 10) AS VARCHAR(1)) + 
        CHAR(ascii('A')+(Abs(Checksum(NewId()))%25)) + 
        LEFT(newid(),@count) Random_Number) 

    SELECT (@automateKey) 

我不知道我怎樣才能從隨機密鑰生成

任何人都可以請該查詢幫助逃避這些特殊字符和數字?提前謝謝了。

+1

您可以檢查最後一個字符串是否含有0,1或O,L然後用 –

+1

你提到隨機一些其它字母代替而不是隨機的價值​​。生成的密鑰是否必須是唯一的(即沒有dups)?解決方案將取決於該要求。 –

+0

對不起,忘了它應該是唯一的... –

回答

0

你的關鍵似乎有3個部分:

第一個字符是其genereted用隨機數0-10:

(Abs(Checksum(NewId()))%10) 

第二個字符是它與產生的隨機字母:

CHAR(ascii('A')+(Abs(Checksum(NewId()))%25)) 

第三部分是可以是字母或數字的三個字符

LEFT(newid(),@count) 

改變前兩個部分以消除不需要的字符並不難,但需要稍微改變第三部分。 相反,你可以離開這個原樣,並添加到末尾while循環來查找和替換不想要的字符 - 用隨機數,O-和L隨機字母0和1:

DECLARE @automateKey VARCHAR(15) 
DECLARE @Length INT = 6 
DECLARE @Count INT = 2 

SET @Length = @Length + 1 
SET @Count = @Count + 1 
--this seems unnecessary , why not just SET @Count = 3 ? 

SELECT @automateKey = 
     (SELECT CAST((ABS(Checksum(NewId())) % 10) AS VARCHAR(1)) + 
       CHAR(ascii('A')+(Abs(Checksum(NewId()))%25)) + 
       LEFT(newid(),@count) Random_Number) 

WHILE (@automateKey LIKE '%0%' OR @automateKey LIKE '%1%') 
BEGIN 
    SELECT @automateKey = REPLACE(@automateKey, '0', (Abs(Checksum(NewId()))%10)) 
    SELECT @automateKey = REPLACE(@automateKey, '1', (Abs(Checksum(NewId()))%10)) 
END 

WHILE (@automateKey LIKE '%O%' OR @automateKey LIKE '%L%') 
BEGIN 
    SELECT @automateKey = REPLACE(@automateKey, 'O', CHAR(ascii('A')+(Abs(Checksum(NewId()))%25))) 
    SELECT @automateKey = REPLACE(@automateKey, 'L', CHAR(ascii('A')+(Abs(Checksum(NewId()))%25))) 
END 

SELECT @automateKey 
+0

非常感謝對於我的支持,但我怎麼能包括這一個插入腳本作爲輸入值表,我需要只有5個字符的隨機生成密鑰。 –

+0

你以前做過嗎?生成密鑰和使用它之間只有兩個額外的循環。 –

2

使用RAND()優於NEWID(),因爲它本質上不是隨機的。

DECLARE 
    @Chars varchar(100) = 'ABCDEFGHJKLMNPQRSTUVWXYZ', 
    @CharsAndNumbers varchar(100) = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ' 

SELECT 
    CONCAT 
    (
     -- Numbers 2-9 
     FLOOR(RAND() * 8 + 2), 

     -- Any UPPER CASE character but not I,O 
     SUBSTRING(@Chars, CONVERT(int, RAND() * LEN(@Chars) + 1), 1), 

     -- Numbers 2-9 and Any UPPER CASE charcter but not I,O 
     SUBSTRING(@CharsAndNumbers, CONVERT(int, (RAND() * LEN(@CharsAndNumbers)) + 1), 1), 
     SUBSTRING(@CharsAndNumbers, CONVERT(int, (RAND() * LEN(@CharsAndNumbers)) + 1), 1), 
     SUBSTRING(@CharsAndNumbers, CONVERT(int, (RAND() * LEN(@CharsAndNumbers)) + 1), 1) 
    ) 

Testing SQL in StackExchange Data Explorer

1

我建議做這樣的事情:

declare @chars varchar(255); 
set @chars = 'ABCDEFGHIJKLMNPQRSTUVWXYZ23456789'; 

declare @i int; 
set @i = 1; 

declare @automateKey = varchar(255); 

set @automatekey = ''; 

while @i <= 5 
begin 
    set @automateKey = @automateKey + substring(@chars, cast(rand() * len(@chars) + 1 as int), 1) 
    set @i = @i + 1; 
end; 

該解決方案有兩個主要組成部分。首先,所有有效的字符都被定義爲一個字符串。其次,它使用while循環來使用rand()設置值。

rand()在SQL Server中以一種奇怪的方式行爲 - 它在給定查詢出現時僅對其計算一次。因此,我通常不想在SELECT聲明中使用它。

我要補充一點,下面就可以更換WHILE循環:

set @automateKey = (substring(@chars, cast(rand() * len(@chars) + 1 as int), 1) + 
        substring(@chars, cast(rand() * len(@chars) + 1 as int), 1) + 
        substring(@chars, cast(rand() * len(@chars) + 1 as int), 1) + 
        substring(@chars, cast(rand() * len(@chars) + 1 as int), 1) + 
        substring(@chars, cast(rand() * len(@chars) + 1 as int), 1) 
        );