12

我正在构建一个系统,它是一个中央存储库,用于存储来自许多其他系统的数据。当其他系统数据更新时,需要同步过程来更新中央存储库。将有一个 sync_action 表来标识中央存储库需要与哪个系统同步以及所需的同步类型。有一组定义的操作不太可能改变。下面是一个精简的系统。

正如我所看到的,我可以通过两种方式解决这个问题:

选项 1 ) 有一个Action表,其中包含 3 个可用的操作。有一个sync_action使用外键引用所需操作的表。

表:系统

ID Description
 1 Slave System 1
 2 Slave System 2

表:行动

ID  Description
 1  Insert
 2  Update
 3  Delete

表:Sync_action

ID  Action  System
 1     1       1
 2     2       1

选项 2)而不是外键使用sync_action.action列上的检查约束,因此只能Insert/Update/Delete插入操作。

表:Sync_action

ID  Action  System
1   Insert    1
2   Update    1

我想知道在决定完整性约束、外键与检查约束之间时,哪些因素会决定哪种方法更好。有类似的线程,但我没有发现它们足够明确。这可能是因为它取决于解释,但任何想法都会受到赞赏。

干杯

4

2 回答 2

8

评论员似乎一致同意:

通常最好对FOREIGN KEY(或多或少静态的)引用表进行约束。原因:

  • 约束很容易“扩展”。要添加或删除选项,您只需在引用表中添加或删除一行。您不必删除约束并重新创建它。更重要的是,如果您在其他表的类似列中也有相同的约束。

  • 您可以附加额外的信息(更多列),如果需要,应用程序可以读取这些信息。

  • ORM 可以更好地处理(阅读:注意)这些约束。他们只需要读取一个表格,而不是元数据。

  • 如果您想更改操作代码,级联效果将处理其他(可能很多)表中的更改。无需编写 UPDATE 查询。

  • 一种特定的 DBMS 尚未实现CHECK约束(耻辱),尽管它确实具有 FK 约束。

正如@pst 提到的(我非常喜欢这种方法),您可以使用合理的代码而不是代理整数 ID。所以,你的桌子可能是:

表:系统

SystemID Description
 1        Slave System 1
 2        Slave System 2

表:行动

ActionCode Description
 I          Insert
 U          Update
 D          Delete

表:SyncAction

ID  ActionCode  SystemID
 1     I          1
 2     U          1
于 2012-02-19T11:33:47.067 回答
4

我认为您混淆了外键约束检查约束之间的区别。

外键约束用于强制引用完整性,而检查约束将列约束为仅包含有效数据。在您的情况下,这似乎是一个微小的差异,但如果我们稍微抽象一下,我希望让它更清楚。

如果我们考虑一个users带有列的表user_id, user_name, address_id, join_date, active, last_active_month;我认识到这不一定是最好的做事方式,但它会为我试图提出的观点服务。

address_id在这种情况下,将其作为约束显然是荒谬的。该列可以有任意数量的值。但是,active假设我们想要一个布尔值y/n只能有两个可能的值,并且last_active_month只能有 12 个可能的值。在这两种情况下,拥有外键是完全荒谬的。只有一定数量的值,并且根据您包含的数据的定义,这些值不能更改。

在您的情况下,虽然您可以进行检查约束,但除非您可以绝对确定actions永远不会更改外键的数量是正确的方法。


在一个稍微不同的问题上,正如@pst 提到的,我看到你被代理键怪物吃掉了。虽然这可以提高性能,但在您设想的大小(3 个值,insert / update / delete)甚至更大的表格中,它所做的只是模糊您想要实现的目标。

不容易看

ID  Action  System
 1     1       1
 2     2       1 

看看发生了什么,但是:

ID  Action  System
 1  insert     1
 2  update     1

更容易阅读;您可能还想考虑对system列做同样的事情 - 我可能会,尽管可能值的数量在此略有跳跃。只是我个人对此事的看法...

于 2012-02-19T11:42:17.393 回答