【问题标题】:Deterministic GUID generation in T-SQLT-SQL 中的确定性 GUID 生成
【发布时间】:2026-01-06 19:50:01
【问题描述】:

我必须准备一个脚本,从几个表中选择数据并在存储了某种多对多关系的表中插入新行。

所以,基本上,我有两个表,其中uniqueidentifier 字段作为主键,另一个表存储这些表中的两个外键和一些附加数据。该表的主键也是uniqueidentifier

INSERT ResultTable ([primaryKey],[foreignA], [foreignB])
    SELECT  newid(), /* <- Can't have it! */
            @foreignKeyA,
            fb.[primaryKey]
    FROM foreignTableB as fb

问题是我不能使用newid() 为我生成的数据生成GUID。要求之一是脚本在相同的表上运行时产生相同的结果(包括主键)。所以我必须想出一个脚本,它将插入带有uniqueidentifier 值的新行,该值是基于另外两个uniqueidentifier 值生成的。

现在,我不知道有任何函数提供从一个 GUID 到另一个 GUID 的映射。大概没有吧。但我还是希望听到一些建议和建议。

还有:

  • 我们可以假设任何一对外键在整个表中都是唯一的
  • 我无法更改上述任何表中主键字段的类型
  • 主要是 SQL Server 2005/2008,但有些可能运行 SQL Server 2000

提前致谢。

【问题讨论】:

  • 这样的声音与取整数#1 和整数#2 并以某种方式将它们组合在一起使得整数#3 可以用作主键非常相似。我不知道有任何方法可以 100% 确定任何两对整数(或 GUID)不会产生相同的“输出”整数。 (散列算法可能会让你接近,如果你能找到一个生成 GUID 值的算法)
  • @Philip Kelley:我很确定我可以通过将两个 GUID 转换为字符串并使用字符进行操作(重新排序)然后将生成的字符串转换回 uniqueidentifier 来做这样的事情。我可能最终会做这样的事情(尽管它非常混乱而且很可能是个坏主意),但我决定我不必这样做

标签: tsql guid uniqueidentifier


【解决方案1】:

您最好的答案是生成一个包含插入语句列表的脚本。 此脚本可以从生成动态 SQL 字符串的另一个脚本生成。 您可能会迭代地执行此操作,每个循环都会调用您的 guid 函数。

这样最后你会得到一个插入列表,可以使用 guid 多次运行,结果相同。

但是生成 guid 的维度之一是时间,因此您将永远无法重现 guid(这确实是重点)

【讨论】:

  • 感谢您(有点晚了)的建议,这几乎就是我昨天最终做的事情。它并没有真正回答关于生成 uniqueidentifier 值的问题,但它解决了我的问题,所以我正在标记你的答案。
【解决方案2】:

您可以先使用CHECKSUM 从多个列中获取整数值,然后将其转换回 GUID:

CREATE TABLE ResultTable ([primaryKey] UNIQUEIDENTIFIER,[foreignA] INT, [foreignB] INT);
CREATE TABLE foreignTableB(primaryKey INT);
INSERT INTO foreignTableB(primaryKey) VALUES (1),(2),(3),(4),(5),(100),(1000);


DECLARE @foreignKeyA INT = 1;

INSERT ResultTable ([primaryKey],[foreignA], [foreignB])
SELECT CAST(CAST(CHECKSUM(@foreignKeyA, fb.primaryKey) AS VARBINARY(4)) AS UNIQUEIDENTIFIER)
      , @foreignKeyA, fb.[primaryKey]
FROM foreignTableB as fb;

SELECT * FROM ResultTable;

db<>fiddle demo

【讨论】: