关于数据设计,循环外键的问题

时间:2011-05-02 15:25:50

标签: sql-server database-design foreign-keys

我正在简化这一点,但我们在一个大型成熟的.net项目使用的大型现有sql2008数据库中有一个User表和一个TestResult表。用户被给予了很多测试,并且这些测试被大量访问,因此为了加快速度,User表包含一个CurrentTestResult和一个PendingTestResult,分别用于上一次测试和正在进行的测试。此外,您不能只查看日期以查找当前测试,因为有时测试可能会失效,与待处理相同。

TestResult当然包含UserID的外键,User有2个指向TestResult的外键。这是很长一段时间,没有太多问题。偶尔某个测试会被固定到用户身上,即使它不是他们的测试,所以很明显它并不完美,我还是需要追踪这个洞。

我们正在转向断开连接的模型,他们告诉我必须删除所有循环键。他们不想暂时删除和重新添加密钥,因为如果该进程失败,他们将不知道该怎么做。不熟悉这个过程我不确定这是否合理,但在我弄清楚修复参考文献的缺点之后,这是一个问题。

我可以看到这个问题的几个解决方案,所有这些都有它们的缺点。

A)最简单的就是删除2个外键。我没有这个问题,因为FK约束只是图片的一半,除非它链接到正确的用户,它仍然无效。我必须权衡风险与代码变化以保持密钥。

B)我可以添加一个交叉引用表来保存当前和待定的链接。我认为这将给予我与现在基本相同的保护,只有轻微的性能差异。我认为圆形键问题消失了,因为它们可以最后插入外部参照。我将进行大量的代码更改。

C)我可以向TestResults添加2列并标记当前和未决记录。这里的问题是现在我必须确保每个用户只设置一个标志,现在每次访问我的数据时我都要查找索引。所以我失去了保护,性能,我仍然有大量的代码更改。

d)?

我确信这是一个相当常见的模式,是否有“正确”的解决方案?

2 个答案:

答案 0 :(得分:0)

您确定选项A实际上会成为性能问题吗?如果您的测试表上有一个索引,其中包含用户FK,然后是按时间顺序递减的内容 - IDENTITY列或测试时间戳,那么当您从TEST表中选择TOP 2时,此索引将非常有用,其中user_id = X你不必担心你的圆形外键会出现问题。

答案 1 :(得分:0)

您的结构对我来说并不清楚,但您可能能够隐藏可更新视图背后的部分或全部更改。

我有一种感觉选择B将是你最好的选择。那你基本上是在谈论这样的桌子,对吗? (航空代码)

create table xref (
    user_id integer not null references users (user_id),
    current_test_result whatever not null references tests (test_id),
    pending_test_result whatever references tests (test_id),
    primary key (Hmmmmm)
);

挂起的测试结果是否可以为空?我想这并不重要 - 如果它必须是可空的,它必须已经在现有表中可以为空。