Sql 如何从整数值创建确定性uniqueidentifier(GUID)

Sql 如何从整数值创建确定性uniqueidentifier(GUID),sql,sql-server,guid,Sql,Sql Server,Guid,注意:这与数据库设计无关,也与GUID的一般使用无关。这是关于在Microsoft SQL server上确定地为测试数据创建这样的GUID 我们正在将数据库从整数标识符迁移到uniqueidentifier数据类型 出于测试目的,我们希望将测试数据集迁移到已知的GUID值,这是基于我们以前的整数值确定的 显然,这并不能马上奏效。如何使用UnitId创建确定性GUID?您可以创建keymap表: CREATE TABLE tab_map(id_old INT PRIMARY KEY, guid

注意:这与数据库设计无关,也与GUID的一般使用无关。这是关于在Microsoft SQL server上确定地为测试数据创建这样的GUID

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

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


显然,这并不能马上奏效。如何使用UnitId创建确定性GUID?

您可以创建keymap表:

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 = ?

您可以创建keymap表:

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的前缀部分,然后将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)
警告:

此实现仅适用于向上的正int值 至最大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

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

我以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)
警告:

此实现仅适用于向上的正int值 至最大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

不要从一个角度思考这个问题。整数由4个字节组成。唯一标识符由16个字节组成。您可以轻松地获取12个固定字节,并将int中的4个字节附加到这些字节的末尾,从而获得适用于所有int值的解决方案:

结果:

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显示为字符串时默认使用的顺序,这就是为什么如果我们要显示死角,我们必须以EFbeade启动二进制文件的原因


当然,还要插入一些常见的警告,即如果您正在创建guid/uniqueidentifiers,但没有使用其中一种指定的方法来生成它们,那么您就不能假设任何关于唯一性的常见保证。

停止从一个角度思考这个问题。整数由4个字节组成。唯一标识符由16个字节组成。您可以轻松地获取12个固定字节,并将int中的4个字节附加到这些字节的末尾,从而获得适用于所有int值的解决方案:

结果:

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显示为字符串时默认使用的顺序,这就是为什么如果我们要显示死角,我们必须以EFbeade启动二进制文件的原因


当然,还要插入一些常见的警告,即如果您正在创建GUID/UniqueIdentifier,但没有使用其中一种指定的方法来生成它们,那么就不能假设任何关于唯一性的常见保证。

GUID不应该基于某个值创建。如果需要,可以基于该值生成哈希,但不要调用它。@Lucasz建议的映射表是在testenv和prod env上执行此操作的方法。执行此操作时要非常小心。如果这成为聚集索引,则会出现一些非常严重的性能问题。不应基于某个值创建GUID。如果需要,可以基于该值生成哈希,但不要调用它。@Lucasz建议的映射表是在testenv和prod env上执行此操作的方法。执行此操作时要非常小心。如果这成为聚集索引,则会出现一些非常严重的性能问题。虽然这有点帮助,但它忽略了我的要点——具有确定性GUID。请记住,这仅适用于测试数据,我想证明我的查询仍按预期工作。对于生产,我们将从全新的数据开始。虽然这有点帮助,但它忽略了我的要点——具有确定性GUID。请记住,这仅适用于测试数据,我想证明我的查询仍按预期工作。对于生产,我们将从全新的数据开始。这是一个很好的答案,我接受它。对我来说,在我的应用程序中,在GUID中使用逐字id值非常方便,我将实现我的解决方案。但同样,这仅用于测试数据目的!这是一个 回答得很好,我接受了。对我来说,在我的应用程序中,在GUID中使用逐字id值非常方便,我将实现我的解决方案。但同样,这仅用于测试数据目的!