更改其他表中由外键引用的表的主键列

时间:2011-05-30 08:03:06

标签: sql sql-server database sql-server-2005 database-design

在我们的数据库中(在SQL Server 2005上),我们有一个“Customers”表,其主键是Client Code,一个代理,bigint IDENTITY(1,1)键;该表由我们的DB中的许多其他表通过外键引用。

我们估计的新CR实现需要我们将ID列类型更改为varchar,客户端代码生成算法从简单的数字级数转换为严格的2-char表示,代码范围从01到99,然后进行像这样:

1A -> 2A -> ... -> 9A -> 1B -> ... 9Z

我对数据库设计还不熟悉,但我在这里闻到了一些严重的问题。首先,这个客户端代码生成算法怎么样?如果我需要客户端代码超出9Z代码限制怎么办?

我有一些问题:这种变化是否可行,表格已经填充了大量数据,并被多个实体引用?如果是这样,您将如何处理此问题,以及如何实现客户端代码生成?

4 个答案:

答案 0 :(得分:2)

我会保留主键,并在生成的客户端代码上创建另一个键(唯一)。 无论如何我会这样做。拥有一个短号主键而不是长char键总是更好。 在某些情况下,您可能更喜欢GUID(出于复制目的),但总是优选int / bigint。 您可以阅读更多herehere

答案 1 :(得分:1)

我对最大的关注你所建议的是你将被限制在360个主要记录中。这似乎是一个小数字。

执行更改是一个多步操作。您需要在核心表及其所有相关表中创建新字段。

要进行就地更新,您需要在核心表中生成代码。然后,您需要更新所有相关表,以使代码基于 ID。然后,您需要将外键约束添加到所有相关表。然后,您需要从所有相关表中删除旧的密钥字段。

我们只在开发服务器中执行了此操作。当我们升级实时数据库时,我们为每个数据库创建了一个新数据库,并使用查询旧数据库并插入新数据库的python脚本复制数据。我现在为每个软件升级更新该脚本,因此核心引擎保持不变,但我可以指定不同的表或数据修改。如果在升级生产时发生意外情况,我会获得原始数据库的完整备份。

支持非身份/ guid代码的一个有力论据是,您需要一个人类可读/令人难忘的代码,并且您需要能够在两个系统之间移动记录。

性能不一定是SQL Server 2005和2008中的一个问题。我们最近进行了一次更改,我们从int int移动到7或8个字符“友好”记录代码。我们预计会出现某种性能损失,但实际上我们看到了性能改进

我们还发现我们需要一种快速生成代码的方法。我们的代码有两部分,一个3个字符的alpha前缀和一个4或5位数的后缀。一旦我们有大量代码(15000-20000),我们发现它很慢将代码解析为前缀和后缀并找到最低的未使用代码(需要几秒钟)。因此,我们分别存储前缀和后缀(在主键表中),以便我们可以快速找到具有特定前缀的下一个可用最低代码。缓存的前缀和后缀几乎使搜索费用。

我们允许更改代码,并且它们通过级联更新规则在外键关系上传播更改的值。我们在核心代码表上保留一个标识密钥,以简化代码的更新。

我们使用ORM,所以我不知道具体的事情需要注意什么。在我们最大的实例中,我们还有大约60,000个主键,但是有数百个表相关,表中包含数百万个与代码表相关的值。

我们获得的一大优势是,在许多情况下,我们不需要进行连接来执行操作。软件中的任何地方都通过友好代码引用事物。我们不必查找int ID(或连接)来执行某些操作。

答案 2 :(得分:0)

新代码生成算法不值得考虑。您可以编写一个程序,只需几行代码即可生成所有可能的代码。把它们放在桌子上,你几乎完成了。您只需要编写一个函数来返回尚未使用的最小函数。这是一个Ruby程序,它将为您提供所有可能的代码。

# test.rb -- generate a peculiar sequence of two-character codes.
i = 1
('A'..'Z').each do |c|
  (1..9).each do |n|
    printf("'%d%s', %d\n", n, c, i)
    i += 1
  end
end

程序将创建一个CSV文件,您应该可以轻松导入到表格中。您需要两列来控制排序顺序。新值不会按照您的要求指定的方式自然排序。

我更关心范围而不是算法。如果您对此要求是正确的,则您只能使用234个客户端代码。如果你错了,范围从“1A”延伸到“ZZ”,你的数量不会少于一千。

要在现有表中实现此要求,您需要遵循一个谨慎的过程。我在测试环境中尝试了几次,然后在生产表上尝试它。 (这只是一个草图。有很多细节。)

  • 创建并填充要映射的双列表 对新CHAR(2)的现有重要事项。
  • 在所有中创建新的CHAR(2)列 需要它们的表格。
  • 更新所有新的CHAR(2)列。
  • 在新的CHAR(2)列上创建新的NOT NULL UNIQUEPRIMARY KEY约束和新的FOREIGN KEY约束。
  • 重写用户界面代码(?)以定位新列。 (如果重命名新的CHAR(2)和旧的BIGINT列,则不需要 。)
  • 设置目标日期以删除旧的BIGINT列和约束。
  • 等等。

答案 3 :(得分:0)

没有真正解决这是否是一个好主意,但您可以更改外键以级联更新。完成此操作后会发生的情况是,当您更新父表中的主键时,子表中的相应键将相应更新。