如何从整数值创建确定性唯一标识符 (GUID)
How to create a deterministic uniqueidentifier (GUID) from an integer value
注意:这与数据库设计无关,也与 GUID 的一般使用无关。这是关于在 Microsoft SQL 服务器上确定性地为测试数据创建此类 GUID。
我们正在将我们的数据库从整数标识符迁移到 uniqueidentifier 数据类型。
出于测试目的,我们希望将我们的测试数据集迁移到已知的 GUID 值,确定性地基于我们以前的整数值
UPDATE Unit
SET UnitGuid = NEWID(UnitId)
显然这不会立即起作用。 如何使用 UnitId 创建确定性 GUID?
您可以创建键盘映射 table:
CREATE TABLE tab_map(id_old INT PRIMARY KEY, guid UNIQUEIDENTIFIER);
INSERT INTO tab_map(id_old, guid)
SELECT id, NEWID()
FROM src_table;
之后你可以使用简单的查询或用函数包装:
SELECT guid
FROM tab_map
WHERE id_old = ?
最后我自己解决了这个问题。这是我的解决方案以供将来参考:
我以 deadbeef-0000-0000-0000-
的形式创建了 GUID 的前缀部分,然后附加一个 "stringified",Id 列的整数值的零填充版本,如 000000000001
, 结果是
DEADBEEF-0000-0000-0000-000000000001
在这个例子中。
这里是这个动作的SQL命令table:
-- 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
别再从想问题了。 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
显示为字符串时默认使用的顺序不同,这就是为什么如果我们想显示DEADBEEF
,我们必须以 efbeadde
)
的形式启动我们的二进制文件
另外,当然,插入通常的警告,如果您正在创建 guids/uniqueidentifiers 但没有使用规定的方法之一来生成它们,那么您不能假设任何关于唯一性的通常保证。
注意:这与数据库设计无关,也与 GUID 的一般使用无关。这是关于在 Microsoft SQL 服务器上确定性地为测试数据创建此类 GUID。
我们正在将我们的数据库从整数标识符迁移到 uniqueidentifier 数据类型。
出于测试目的,我们希望将我们的测试数据集迁移到已知的 GUID 值,确定性地基于我们以前的整数值
UPDATE Unit
SET UnitGuid = NEWID(UnitId)
显然这不会立即起作用。 如何使用 UnitId 创建确定性 GUID?
您可以创建键盘映射 table:
CREATE TABLE tab_map(id_old INT PRIMARY KEY, guid UNIQUEIDENTIFIER);
INSERT INTO tab_map(id_old, guid)
SELECT id, NEWID()
FROM src_table;
之后你可以使用简单的查询或用函数包装:
SELECT guid
FROM tab_map
WHERE id_old = ?
最后我自己解决了这个问题。这是我的解决方案以供将来参考:
我以 deadbeef-0000-0000-0000-
的形式创建了 GUID 的前缀部分,然后附加一个 "stringified",Id 列的整数值的零填充版本,如 000000000001
, 结果是
DEADBEEF-0000-0000-0000-000000000001
在这个例子中。
这里是这个动作的SQL命令table:
-- 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
别再从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
显示为字符串时默认使用的顺序不同,这就是为什么如果我们想显示DEADBEEF
,我们必须以 efbeadde
)
另外,当然,插入通常的警告,如果您正在创建 guids/uniqueidentifiers 但没有使用规定的方法之一来生成它们,那么您不能假设任何关于唯一性的通常保证。