我正在尝试创建一个存储过程,以从 SQL Server 2016 上的以下字符集随机生成两个唯一的字母数字字符:
ABCDEFGHIJKLMNPQRSTUVWXYZ0123456789
(35 个字符集)。然后,随机值将存储在 AspNetUsers
表的自定义列中。
目前,
AspNetUsers
表中仅存储 132 个唯一的 2 字符值,而总共可以有 1,225 种排列。这是基于排列公式:n! / (n - r)!
或 35! / (35 - 2)! = 1225
。
以下代码基于此示例有时有效,而有时则变成无限循环。外部 WHILE 确保该值在存储它的表中是唯一的。
DECLARE @length int, @charpool varchar(256), @poollength int,
@loopcount int, @randomstring varchar(100)
SET @Length = 2
-- define allowable character explicitly - easy to read this way an easy to
SET @CharPool = 'ABCDEFGHIJKLMNPQRSTUVWXYZ0123456789'
SET @PoolLength = Len(@CharPool)
SET @LoopCount = 0
SET @RandomString = ''
WHILE (SELECT count(*) FROM AspNetUsers anu WHERE anu.CustomId = @randomstring) > 0 BEGIN
WHILE (@LoopCount < @Length) BEGIN
SELECT @RandomString = @RandomString +
SUBSTRING(@Charpool, CONVERT(int, RAND() * @PoolLength) + 1, 1)
SELECT @LoopCount = @LoopCount + 1
END
END
PRINT @randomstring
你可以这样做:
-- Seed existing
DROP TABLE IF EXISTS #aspusers
CREATE TABLE #aspusers (id int IDENTITY, somerandomValue varchar(2) UNIQUE)
DECLARE @length int, @charpool varchar(256), @poollength int,
@loopcount int, @randomstring varchar(100)
SET @Length = 2
-- define allowable character explicitly - easy to read this way an easy to
SET @CharPool = 'ABCDEFGHIJKLMNPQRSTUVWXYZ0123456789'
;WITH data AS (
SELECT TOP(len(@charpool)) row_number() OVER(ORDER BY @@spid) AS rank
FROM sys.objects so
)
INSERT INTO #aspusers (somerandomValue)
SELECT TOP 132 chrs
FROM (
SELECT substring(@charpool, d.rank, 1) + substring(@charpool, d2.rank, 1) AS chrs
FROM data d
CROSS JOIN data d2
) x
ORDER BY NEWID()
-- Generate new random value
;WITH data AS (
SELECT TOP(len(@charpool)) row_number() OVER(ORDER BY @@spid) AS rank
FROM sys.objects so
)
SELECT TOP 1 @randomstring = x.chrs
FROM data d
CROSS JOIN data d2
CROSS apply (
SELECT substring(@charpool, d.rank, 1) + substring(@charpool, d2.rank, 1) AS chrs
) x
WHERE NOT EXISTS(
SELECT 1
FROM #aspusers asp
WHERE asp.somerandomValue = x.chrs
)
ORDER BY NEWID()
-- Output
SELECT @randomstring, *
FROM #aspusers
主要思想是生成 1 到 len(charpool) 之间的数字列表,然后使用 SUBSTRING 创建字符组合。
要生成新的随机值,只需添加一个
WHERE NOT EXISTS
来检查原始表。