如何从整数值创建确定性唯一标识符(GUID)

时间:2018-08-28 15:07:07

标签: sql sql-server guid

注意:这与数据库设计无关,也不与GUID的一般用法有关。这是关于在Microsoft SQL服务器上确定性地创建用于测试数据的GUID。

我们正在将数据库从整数标识符迁移到uniqueidentifier数据类型。

出于测试目的,我们希望根据以前的整数值确定性地将测试数据集迁移到已知的GUID值

UPDATE Unit
SET UnitGuid = NEWID(UnitId)

显然,这无法立即生效。 如何使用UnitId创建确定性GUID?

3 个答案:

答案 0 :(得分:5)

您可以创建键盘映射表:

CREATE TABLE tab_map(id_old INT PRIMARY KEY, guid UNIQUEIDENTIFIER);

INSERT INTO tab_map(id_old, guid)
SELECT id, NEWID()
FROM src_table;

DBFiddle Demo

之后,您可以使用简单查询或使用函数包装:

SELECT guid
FROM tab_map
WHERE id_old = ?

答案 1 :(得分:2)

停止从"string" perspective思考问题。 int由4个字节组成。 uniqueidentifier由16个字节组成。您可以轻松获取12个固定字节,并将int的四个字节附加到这些字节的末尾,并获得适用于所有int值的解决方案:

declare @Unit table
(
UniqueColumn UNIQUEIDENTIFIER DEFAULT NEWID(),
Characters VARCHAR(10),
IntegerId int
)

-- Add *3* data rows
INSERT INTO @Unit(Characters, IntegerId) VALUES ('abc', 1111),('def', 2222),('ghi',-17)

-- Deterministically creates a uniqueidentifier value out of an integer value. 
DECLARE @GuidPrefix binary(12) = 0xefbeadde0000000000000000
UPDATE @Unit 
    SET UniqueColumn = CONVERT(uniqueidentifier,@GuidPrefix + CONVERT(binary(4),IntegerId))

-- Check the result
SELECT * FROM @Unit

结果:

UniqueColumn                         Characters IntegerId
------------------------------------ ---------- -----------
DEADBEEF-0000-0000-0000-000000000457 abc        1111
DEADBEEF-0000-0000-0000-0000000008AE def        2222
DEADBEEF-0000-0000-0000-0000FFFFFFEF ghi        -17

(由于各种原因,我们必须以与显示uniqueidentifier为字符串时默认使用的顺序不同的顺序提供前四个字节,这就是为什么我们要显示{{ 1}},我们必须以DEADBEEF)开头二进制文件

当然,还要插入通常的警告,如果您正在创建guids / uniqueidentifier,但未使用规定的方法之一生成它们,那么您将无法承担任何有关唯一性的常规保证。

答案 2 :(得分:0)

我最终自己解决了这个问题。这是我的解决方案,供以后参考:

我以deadbeef-0000-0000-0000-的形式创建GUID的前缀部分,然后向其附加ID列的整数值的“字符串化”,零填充版本,例如000000000001,以得到结果在

DEADBEEF-0000-0000-0000-000000000001

在此示例中。

这是在整个表上执行此操作的SQL命令:

-- Deterministically creates a uniqueidentifier value out of an integer value. 
DECLARE @GuidPrefix nvarchar(max) = N'deadbeef-0000-0000-0000-';  -- without the last 12 digits
UPDATE Unit 
    SET UniqueColumn = 
    (SELECT @GuidPrefix + RIGHT('000000000000' + CAST(IntegerId AS NVARCHAR (12)), 12 ) AS NUMBER_CONVERTED)

警告:

  • 此实现仅适用于正整数值(向上 到2147483647以下)
  • 这仅用于测试数据!使用是 强烈建议不要使用生产数据!

这是一个完整的工作示例:

-- Create an example table with random GUID's
CREATE TABLE Unit
(
UniqueColumn UNIQUEIDENTIFIER DEFAULT NEWID(),
Characters VARCHAR(10),
IntegerId int
)

-- Add 2 data rows
INSERT INTO Unit(Characters, IntegerId) VALUES ('abc', 1111)
INSERT INTO Unit(Characters, IntegerId) VALUES ('def', 2222)

-- Deterministically creates a uniqueidentifier value out of an integer value. 
DECLARE @GuidPrefix nvarchar(max) = N'deadbeef-0000-0000-0000-';  -- without the last 12 digits
UPDATE Unit 
    SET UniqueColumn = 
    (SELECT @GuidPrefix + RIGHT('000000000000' + CAST(IntegerId AS NVARCHAR (12)), 12 ) AS NUMBER_CONVERTED)

-- Check the result
SELECT * FROM Unit

结果:

UniqueColumn                            Characters IntegerId
--------------------------------------- ---------- ---------
DEADBEEF-0000-0000-0000-000000001111    abc        1111
DEADBEEF-0000-0000-0000-000000002222    def        2222