2

我有一个表结构,我不确定如何创建最好的方法。

基本上我有两个表,tblSystemItems 和 tblClientItems。我有第三个表,其中有一列引用“项目”。问题是,此列需要引用系统项或客户端项——哪个都没有关系。系统项目的键在 1..2^31 范围内,而客户端项目的键在 -1..-2^31 范围内,因此永远不会有任何冲突。

每当我查询这些项目时,我都是通过在两个表的内容之间执行 UNION ALL 的视图来完成的。

因此,最佳情况下,我希望将外键引用作为视图的结果,因为视图将始终是两个表的联合 - 同时仍保持 ID 唯一。但我不能这样做,因为我无法引用视图。

现在,我可以删除外键,一切都很好。但是,我真的很想有一些参考检查和级联删除/设置 null 功能。除了触发器,还有什么方法可以做到这一点?

4

6 回答 6

1

对于迟到的答案,我感到很抱歉,我遇到了严重的周末炎病例。

至于使用第三个表来包含来自客户端和系统表的 PK - 我不喜欢这样,因为这会使同步过于复杂,并且仍然需要我的应用程序知道第三个表。

出现的另一个问题是我有第三个表需要引用一个项目——无论是系统还是客户端,都没有关系。将表分开基本上意味着我需要有两列,一个 ClientItemID 和一个 SystemItemID,每个列都有一个可以为空的表的约束 - 相当难看。

我最终选择了不同的解决方案。整个问题在于轻松地将新系统项同步到表中,而不会弄乱客户端项,避免冲突等。

我最终只创建了一个表,Items。Items 有一个名为“SystemItem”的位列,它定义了显而易见的内容。在我的开发/系统数据库中,我将 PK 作为一个 int 身份(1,1)。在客户端数据库中创建表后,标识键更改为 (-1,-1)。这意味着客户项目是消极的,而系统项目是积极的。

对于同步,我基本上忽略 (SystemItem = 1) 的任何内容,同时使用 IDENTITY INSERT ON 同步其余内容。因此,我能够在完全忽略客户端项目并避免冲突的同时进行同步。我还可以仅引用一个涵盖客户端和系统项目的“项目”表。唯一要记住的是修复标准集群键,使其下降以避免客户端插入新项目时的各种页面重组(客户端更新与系统更新的比例为 99%/1%)。

于 2008-11-10T20:45:41.470 回答
0

您可能需要一个表,例如 tblItems,它只存储两个表的所有主键。插入项目需要两个步骤来确保当项目被输入到 tblSystemItems 表中时,PK 被输入到 tblItems 表中。

然后第三个表有一个到 tblItems 的 FK。在某种程度上 tblItems 是其他两个项目表的父项。要查询一个项目,有必要在 tblItems、tblSystemItems 和 tblClientItems 之间创建一个 JOIN。

[EDIT-for comment below] 如果 tblSystemItems 和 tblClientItems 控制他们自己的 PK,那么你仍然可以让他们。您可能会先插入 tblSystemItems,然后再插入 tblItems。当您使用 Hibernate 之类的工具实现继承结构时,您最终会得到类似的结果。

于 2008-11-06T14:13:28.253 回答
0

您可以为引用项目的表创建一个唯一 id(db 生成 - 序列、autoinc 等),并创建两个额外的列(tblSystemItemsFKtblClientItemsFk)分别引用系统项目和客户端项目 -一些数据库允许您拥有可以为的外键。

如果您使用的是 ORM,您甚至可以仅根据列信息轻松区分客户端项目和系统项目(这样您就不需要负标识符来防止 ID 重叠)。

使用更多的 bakcground/context 可能更容易确定最佳解决方案。

于 2008-11-06T14:20:28.520 回答
0

添加一个名为 Items 的表,其 PK ItemId 和一个名为 ItemType = "System" 或 "Client" 的单列,然后 ClientItems 表 PK(名为 ClientItemId)和 SystemItems PK(名为 SystemItemId)也都是 Items.ItemId 的 FK,(这些关系是零对一的关系 (0-1)

然后在引用项目的第三个表中,只需让它的 FK 约束引用这个额外(项目)表中的 itemId ......

如果您使用存储过程来实现插入,只需让插入项目的存储过程首先将新记录插入 Items 表,然后使用该表中自动生成的 PK 值将实际数据记录插入 SystemItems 或ClientItems(取决于它是)作为同一个存储过程调用的一部分,使用系统插入到 Items 表 ItemId 列中的自动生成(身份)值。

这称为“子类化”

于 2008-11-06T14:51:00.393 回答
0

我一直对你的桌子设计感到困惑。我不确定它是否正确。我意识到第三个表可能只是提供详细信息,但我不禁认为主键实际上是您的 ITEM 表中的一个,而 FOREIGN 键是您的系统和客户端项目表中的键。然后,您只需要从 Item 到系统和客户端项目表进行正确的外部连接,所有约束都可以正常工作。

于 2008-11-06T19:53:41.590 回答
0

我正在使用的数据库中有类似的情况。我在每个称为 EntityID 的表上都有一个“候选键”。然后,如果有一个表需要引用多个其他表中的项目,我使用 EntityID 来引用该行。我确实有一个 Entity 表来交叉引用所有内容(因此 EntityID 是 Entity 表的主键,而所有其他 EntityID 都是 FK),但我发现自己并不经常使用 Entity 表。

于 2008-11-11T04:50:59.963 回答