【问题标题】:I need to be able to generate non-repetitive 8 character random alphanumeric for 2.5 million records我需要能够为 250 万条记录生成非重复的 8 字符随机字母数字
【发布时间】:2019-03-16 12:56:04
【问题描述】:

我需要能够在具有近 250 万条记录的表上每行应用唯一的 8 个字符串。

我试过这个:

UPDATE MyTable 
    SET [UniqueID]=SUBSTRING(CONVERT(varchar(255), NEWID()), 1, 8)

这可行,但是当我检查 ID 的唯一性时,我会收到重复的内容

SELECT [UniqueID], COUNT([UniqueID]) 
FROM NicoleW_CQ_2019_Audi_CR_Always_On_2019_T1_EM
GROUP BY [UniqueID]
HAVING COUNT([UniqueID]) > 1

我真的很想更新表格,如上所述,如果可能的话,只需要一行简单的代码。

【问题讨论】:

标签: sql sql-server


【解决方案1】:

这是一种使用临时表来保证唯一性的方法

使用唯一的随机 8 个字符代码创建并填充 #temporary 表。

下面的 SQL 使用 FOR XML 技巧在 BASE62 中生成代码:[A-Za-z0-9]

Examples : 8Phs7ZYl, ugCKtPqT, U9soG39q

GUID 仅使用字符 [0-9A-F]
对于 8 个字符,可以生成 16^8 = 4294967296 种组合。
而使用 BASE62 则有 62^8 = 2.183401056e014 组合。
因此,使用 BASE62 生成重复的几率显着降低。

临时表的记录数应与目标表相同。
此示例仅生成 100000 个代码。但你明白了。

IF OBJECT_ID('tempdb..#tmpRandoms') IS NOT NULL DROP TABLE #tmpRandoms;
CREATE TABLE #tmpRandoms (
    ID INT PRIMARY KEY IDENTITY(1,1), 
    [UniqueID] varchar(8),
    CONSTRAINT UC_tmpRandoms_UniqueID UNIQUE ([UniqueID])
);

WITH DIGITS AS
(  
    select n 
    from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n)
),
NUMS AS
(
    select (d5.n*10000 + d4.n*1000 + d3.n*100 + d2.n * 10 + d1.n) as n
    from DIGITS d1
    cross join DIGITS d2
    cross join DIGITS d3
    cross join DIGITS d4
    cross join DIGITS d5
)
INSERT INTO #tmpRandoms ([UniqueID])
SELECT DISTINCT LEFT(REPLACE(REPLACE((select CAST(NEWID() as varbinary(16)), n FOR XML PATH(''), BINARY BASE64),'+',''),'/',''), 8) AS [UniqueID]
FROM NUMS;

然后用它更新你的表

WITH CTE AS
(
    SELECT ROW_NUMBER() OVER (ORDER BY ID) AS RN, [UniqueID]
    FROM YourTable
)
UPDATE t 
SET t.[UniqueID] = tmp.[UniqueID]
FROM CTE t
JOIN #tmpRandoms tmp ON tmp.ID = t.RN;

rextester here

的测试

【讨论】:

    【解决方案2】:

    你可以只使用数字并分配一个随机值吗?

    with toupdate as (
          select t.*,
                 row_number() over (order by newid()) as random_enough
          from mytable t
         )
    update toupdate
        set UniqueID = right(concat('00000000', random_enough), 8);
    

    【讨论】:

    • 从来没有直接通过 cte 更新过,我怎么这么老了?非常好!
    【解决方案3】:

    【讨论】:

      猜你喜欢
      • 2019-02-23
      • 2013-08-06
      • 2011-06-18
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 2021-04-05
      • 2011-08-18
      相关资源
      最近更新 更多