2017-08-04 80 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) 
        );