【问题标题】:Moving from ints to GUIDs as primary keys从整数到 GUID 作为主键
【发布时间】:2010-09-13 09:11:51
【问题描述】:

我使用了几个带有整数主键的引用表。现在我想将整数更改为 GUID,使所有引用保持不变。最简单的方法是什么?

谢谢!

加法

我确实了解这个过程,所以我需要更详细的建议,例如,如何填写新的 GUID 列。使用默认值 newid() 是正确的,但是对于已经存在的行呢?

【问题讨论】:

  • 作为对未来读者的警告:仅在谨慎考虑后才将唯一标识符 (GUID) 用作主键:通常情况下它是不好的想法。

标签: sql sql-server foreign-keys primary-key guid


【解决方案1】:
  • 为 guid 创建一个新列 主表中的值。使用 uniqueidentifier 数据类型,使其 不使用 newid() 默认为 null 所以 将填充所有现有行。
  • 创建新的唯一标识符列 在子表中。
  • 运行更新语句以使用现有的 int 关系来构建公会关系以引用实体。
  • 删除原来的 int 列。

此外,请在数据/索引页面中留出一些空间(指定填充因子

【讨论】:

    【解决方案2】:

    首先:天哪,为什么?!?!?

    其次,您必须先将 GUID 列添加到所有表中,然后根据 int 值填充它们。完成后,您可以将 GUID 设置为主键/外键,然后删除 int 列。

    要更新值,你会做类似的事情

    1. 在主键表中设置新的 GUID
    2. 运行这个:

    .

    UPDATE foreignTable f
    SET f.guidCol = p.guidCol
    FROM primaryTable p
    WHERE p.intCol = f.intCol
    

    【讨论】:

    • 我同意格伦的观点。对于 PK,我会坚持使用整数。如果您需要更多记录,请使用 bigints。如果您需要全局标识符,请使用 URI 之类的内容作为辅助键,并坚持使用整数作为 PK。
    • 但是如何在主键表中设置新的GUID?
    • 2 Alexander Prokofyev:将所有“guid”PK 列的默认子句设置为“newid()”。 2 marxidad:如果您需要在 DB 以外的其他环境中创建级联记录(例如 winforms 应用程序),则使用 Guid 而不是 (big)int 非常有用。
    • 2 TcKs:但是 GUID 为空的旧记录呢?
    • 更新 some_table SET some_guid_column = newid() WHERE some_guid_column 为空
    【解决方案3】:

    这与实现分布式计算模型的系统相关。如果在系统中持久化信息时需要系统知道主键,则使用 ONE 处理程序维护的自动递增主键会降低系统速度。相反,您需要一种类似于 GUID 生成器的机制来创建主键(请记住,主键的真正特征是它的唯一性)。因此,我可以扩展多个服务,每个服务都创建自己的主键,彼此独立。

    我之前有过这样做的可疑特权,基本上我要做的就是将整个该死的数据库导出为 XML。接下来,我有一个 Java 应用程序,它使用 java.util.Random 的 nextLong() 函数将主键替换为新的 guid 键。之后,我将整个内容重新导入数据库。

    当然,我第一次尝试将XML文件导入回来时,我忘记关闭主键字段的自动编号功能,所以请从我的错误中吸取教训。我确信有更好的方法可以做到这一点,但这是一种快速而肮脏的方法......而且它奏效了。如果您想知道,该项目是为了使应用程序规模化。

    【讨论】:

      【解决方案4】:

      是的,我和格伦在一起……实际上,在他发布之前,我一直在犹豫是否要发布相同的内容……

      您为什么不希望将自动增量 int 主键与您的 GUID 分开?它更加灵活,您只需将 GUID 列编入索引,这样您的查询就有了良好的性能...


      至于灵活性,我喜欢将我的 id 保持为自动增量整数,因为这样其他看似唯一且值得主键的项目可以更改。

      灵活性的一个很好的例子是如果您使用用户名作为主键。即使它们是独一无二的,也很高兴能够改变它们。如果用户使用电子邮件地址作为用户名怎么办?能够更改用户名并且不影响您的所有查询是一大优势,我怀疑您的 GUID 可能也是如此......

      【讨论】:

      • 我对使用特殊值进行 PK 有最好的体验。因为那样的话,改变记录中的任何值都没有问题(例如:因为用户打错了)。
      【解决方案5】:

      我认为,您必须手动操作。或者你可以为它写一些实用程序。场景应该是:

      • 使用新的“guid”列复制“int”PK/FK 列。
      • 为“guid”PK 列生成新值。
      • 使用指定值更新“guid”FK 列中的值(您可以通过“int”PK 找到记录)。
      • 删除带有“int”PK/FK 列的引用(关系)。
      • 使用“guid”PK/FK 列创建类似的引用(关系)。
      • 删除“int”PK/FK 列。

      【讨论】:

        【解决方案6】:

        这是一个非常好的选择。对于我的一个应用程序,我从 longs 切换到 UUID,我并不后悔。如果您使用 MS SQL Server,它包含在标准中(我使用 postgresql,它仅包含在 8.3 之后的标准中)。

        Glenn Slaven 所述,您可以根据当前记录中的键重新创建 UUID。请注意,尽管它们不会是独一无二的,但这样很容易保持关系完整。您在移动后创建的新记录将是唯一的。

        【讨论】:

          【解决方案7】:

          不要这样做!我们开始使用 GUID,现在我们几乎完成了将 INT 作为 PK 的迁移;我们保留 GUID 用于日志记录(以及一些表,呃,“可协商的关系完整性”;)),但是使用 int 的速度提升是惊人的。

          这只有在表格行数超过数百万时才真正显现出来,请注意。

          到目前为止,我们最大的错误是使用 NEWID() 作为我们(顺序)日志表的 PK - 当我们意识到我们的错误时,我们非常头疼。

          【讨论】:

          • 可能是不正确的indeces?您没有关于 guid PK 的聚集索引而不是一些更好的 FK。它经常出错。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多