Мне нужно иметь возможность генерировать бесповторную 8-символьную случайную буквенно-цифровую для 2,5 миллионов записей - PullRequest
1 голос
/ 16 марта 2019

Мне нужно иметь возможность применять уникальные 8-символьные строки в строке к таблице, содержащей почти 2,5 миллиона записей.

Я пробовал это:

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

Что работает, но когда я проверяю уникальность идентификаторов, я получаю дубликаты

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

Мне бы очень хотелось обновить таблицу, как указано выше, просто простой строкой кода, если это возможно.

Ответы [ 3 ]

2 голосов
/ 16 марта 2019

Вот способ, который использует временную таблицу для обеспечения уникальности.

Создайте и заполните # временную таблицу уникальными случайными 8-символьными кодами.

Приведенный ниже 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;

Затем обновите таблицу: 1020 *

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 здесь

2 голосов
/ 16 марта 2019

Вы можете просто использовать числа и назначить случайное значение?

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);
0 голосов
/ 16 марта 2019

См .: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/a289ed64-2038-415e-9f5d-ae84e50fe702/generate-random-string-of-length-5-az09?forum=transactsql

Изменить: DECLARE @s char (5) и SELECT TOP (5) c1, чтобы установить желаемую длину.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...