此问题与此thread有关,不确定我是否应该在该帖子中发布此新问题或创建新帖子,但担心它可能不会被视为内容中的后续问题老帖子......
或者是否有更好的方法来解决这个问题?说没有循环...?
SELECT * INTO #ControlTable FROM tempmaster
DECLARE @ei varchar(max)
DECLARE @r varchar(8)
WHILE EXISTS (SELECT * FROM #ControlTable)
BEGIN
SELECT @ei = (SELECT TOP 1 externalid FROM #ControlTable ORDER BY externalid ASC)
-- CREATE UNIQUE RANDOM ID
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
-- REPLACE OLD ID
UPDATE tempmaster SET externalid = @r WHERE externalid = @ei
DELETE #ControlTable WHERE externalid = @ei
/*TESTING*/
--SELECT @ei AS EI, @r AS [newID]
--SELECT * FROM #ControlTable
--SELECT * FROM tempmaster WHERE externalid = @ei OR externalid = @r
END
drop table #ControlTable
这是基于集合的方法的尝试概述
DECLARE @r varchar(8);
SELECT oid, startdate, enddate,
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())
as externalid
FROM MasterTable
答案 0 :(得分:2)
虽然你的循环不是我接近问题的方法(基于集合的方法要好得多),但问题是你没有在循环内重新初始化@r
。
所以,添加:
set @r = NULL;
到循环的开头。
答案 1 :(得分:1)
我没有对此进行测试,但您可以通过此UPDATE
语句替换循环。它要求您当前的 enternalid 值是唯一的:
WITH cte AS (
SELECT
externalid,
concat(
substring(chars, num % 62, 1),
substring(chars, (num/62) % 62, 1),
substring(chars, (num/3844) % 62, 1),
substring(chars, (num/238328) % 62, 1),
substring(chars, (num/14776336) % 62, 1),
substring(chars, (num/916132832) % 62, 1),
substring(chars, (num/56800235584) % 62, 1),
substring(chars, (num/3521614606208) % 62, 1)
) AS unique_string8
FROM (
SELECT
externalid,
(rn * 34524689549219 + seed) % 199689672115897 AS num,
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' AS chars
FROM (
SELECT externalid,
ROW_NUMBER() OVER (ORDER BY externalid) AS rn,
0 AS seed
FROM tempmaster
) AS subq1
) AS subq2
)
UPDATE t
SET externalid = cte.unique_string8
FROM tempmaster t
INNER JOIN cte
ON cte.externalid = t.externalid;
我们的想法是 cte 查询使用新的8个字符的密钥映射现有的 externalid ,然后使用该映射执行更新。
字符取自具有62个可能字符的文字字符串。值 num 是素数加上一些种子(在这种情况下为0)的倍数,并通过将模数取为接近8个字符的可能字符串数的素数而保持在限制范围内。
然后将得到的数字转换为8个字符的字符串,就好像该数字用62个碱基表示一样。公式中的分母是62的幂。
这样,保证您永远不会得到重复(除非您有比8个字母组合更多的记录)。
没有随机部分,因此它将始终生成相同的系列,但您可以将种子值更改为任何整数以更改将生成的系列。