我有一个表结构,我不确定如何创建最好的方法。
基本上我有两个表,tblSystemItems和tblClientItems。我有一个第三个表,其中有一个引用'Item'的列。问题是,此列需要引用系统项或客户端项 - 这与哪个无关。系统项目的密钥在1..2 ^ 31范围内,而客户端项目的密钥在-1 ..- 2 ^ 31范围内,因此永远不会有任何冲突。
每当我查询这些项目时,我都是通过一个在两个表的内容之间执行UNION ALL的视图来完成的。
因此,最佳地,我想将外键引用视图的结果,因为视图将始终是两个表的并集 - 同时仍保持ID唯一。但我不能这样做,因为我无法引用一个视图。
现在,我可以放下外键,一切都很好。但是,我真的想要一些参考检查和级联删除/设置null功能。除了触发器之外,有没有办法做到这一点?
答案 0 :(得分:1)
对于迟到的回答感到抱歉,我对周末炎症的严重情况感到震惊。
至于利用第三个表来包含来自客户端和系统表的PK - 我不喜欢它,因为这只会使同步过于复杂,仍然需要我的应用知道第三个表。
出现的另一个问题是我有第三个表需要引用一个项目 - 无论是系统还是客户端,都没关系。将表分开基本上意味着我需要有两个列,一个ClientItemID和一个SystemItemID,每个列都有一个具有可为空性的表的约束 - 相当丑陋。
我最终选择了不同的解决方案。整个问题是轻松地将新系统项同步到表中而不会弄乱客户端项,避免冲突等。
我最终创建了一个表,Items。 Items有一个名为“SystemItem”的位列,它定义了明显的。在我的开发/系统数据库中,我将PK作为int标识(1,1)。在客户端数据库中创建表后,身份密钥将更改为(-1,-1)。这意味着客户端项目为负数,而系统项目为正数。
对于同步,我基本上忽略任何(SystemItem = 1),同时使用IDENTITY INSERT ON同步其余部分。因此,我可以在完全忽略客户端项目和避免冲突的同时进行同步。我还能够引用一个涵盖客户端和系统项的“项目”表。唯一要记住的是修复标准的群集密钥,以便在客户端插入新项目时(客户端更新与系统更新的比例为99%/ 1%)下降以避免各种页面重构。
答案 1 :(得分:0)
你可能需要一个表来说tblItems只存储两个表的所有主键。插入项目需要两个步骤,以确保在将项目输入tblSystemItems表时将PK输入到tblItems表中。
然后第三个表有一个FK到tblItems。在某种程度上,tblItems是其他两个项表的父级。要查询Item,需要在tblItems,tblSystemItems和tblClientItems之间创建JOIN。
[编辑 - 以下评论]如果tblSystemItems和tblClientItems控制他们自己的PK,那么你仍然可以让他们。您可能先插入tblSystemItems然后插入tblItems。当你使用像Hibernate这样的工具实现一个继承结构时,你会得到类似的东西。
答案 2 :(得分:0)
您可以为引用项目的表创建唯一ID(db generated - sequence,autoinc等),并创建另外两列( tblSystemItemsFK 和 tblClientItemsFk )您可以分别引用系统项和客户端项目 - 某些数据库允许您拥有可以为空的的外键。
如果您正在使用ORM,您甚至可以根据列信息轻松区分客户项目和系统项目(这样您就不需要使用否定标识符来防止ID重叠)。
通过更多的bakcground / context,可能更容易确定最佳解决方案。
答案 3 :(得分:0)
添加一个名为Items的表,其中包含PK ItemiD,而名为ItemType =“System”或“Client”的单个列则具有ClientItems表PK(名为ClientItemId),而SystemItems PK(名为SystemItemId)也都是FK到Items。 ItemId,(这些关系为零对一关系(0-1)
然后在你的第三个引用一个项目的表中,让它的FK约束引用这个额外(Items)表中的itemId ......
如果您使用存储过程来实现插入,只需让插入项的存储过程首先在Items表中插入一条新记录,然后使用该表中自动生成的PK值将实际数据记录插入SystemItems或ClientItems(取决于它是什么)作为同一存储proc调用的一部分,使用系统插入Items表ItemId列的自动生成(标识)值。
这称为“SubClassing”
答案 4 :(得分:0)
我一直在为你的桌子设计感到困惑。我不确定它是对的。我意识到第三个表可能只是提供详细信息,但我不禁想到主键实际上是ITEM表中的主键,FOREIGN键是系统和客户端项表中的键。然后,您只需要从Item到系统和客户端项表执行正确的外连接,并且所有约束都可以正常工作。
答案 5 :(得分:0)
我在使用的数据库中有类似的情况。我在每个表上都有一个“候选键”,我称之为EntityID。然后,如果有一个表需要引用多个其他表中的项,我使用EntityID来引用该行。我有一个Entity表来交叉引用所有内容(因此EntityID是Entity表的主键,所有其他EntityID都是FK),但我没有发现自己经常使用Entity表。