Foreign key vs check constraint for integrity

隐身守侯 提交于 2019-11-28 09:15:33

The commentators seems to umanimously agree:

It's generally better to have a FOREIGN KEY constraint to a (more or less static) reference table. Reasons:

  • The constraint is easily "extendable". To add or remove an option, you only have to add or remove a row from the refernce table. You don't have to drop the constraint and recreate it. Even more, if you have same constraint in similar columns in other tables, too.

  • You can have extra information attached (more columns), that can be read by the applications if needed.

  • ORMs can deal better with (Read: be aware of) these constraints. They just have to read a table, not the meta-data.

  • If you want to change the Action codes, the cascading effects will take care of the changes in other (possibly many) tables. No need to write UPDATE queries.

  • One particular DBMS has not yet implemented CHECK constraints (shame), although it does have FK ones.

As @pst mentioned (and I prefer this approach very much), you can use a sensible code instead of a surrogate integer ID. So, your table could be:

Table: System

SystemID Description
 1        Slave System 1
 2        Slave System 2

Table: Action

ActionCode Description
 I          Insert
 U          Update
 D          Delete

Table: SyncAction

ID  ActionCode  SystemID
 1     I          1
 2     U          1

I think you're confusing the difference between a foreign key constraint and a check constraint.

A foreign key constraint is there to enforce referential integrity and a check constraint constrains a column to containing only valid data. In your case this may seem like a minor difference but if we abstract it slightly I hope to make it clearer.

If we consider a table users with the columns user_id, user_name, address_id, join_date, active, last_active_month; I recognise that this is not necessarily the best way of doing things but it'll serve for the point I'm trying to make.

In this case it's patently ridiculous to have address_id as a constraint. This column could have any number of values. However, active, assuming we want a boolean y/n can only have two possible values and last_active_month can only have 12 possible values. In both these cases it's completely ridiculous to have a foreign key. There are only a certain number of values and by the definition of the data you are including these values cannot change.

In your case, while you could go for a check constraint, unless you can be absolutely certain that the number of actions will never change a foreign key is the correct way to go.


On a slightly separate matter, and as @pst mentioned, I see you've been eaten by the surrogate key monster. While this can result in performance improvements, in a table of the size you're envisaging ( 3 values, insert / update / delete ) or even a larger one all it serves to do is obscure what you're trying to achieve.

It's not easy to look at

ID  Action  System
 1     1       1
 2     2       1 

and see what's going on, but:

ID  Action  System
 1  insert     1
 2  update     1

is far easier to read; you may also want to consider doing the same for the system column - I probably would, though the number of possible values jumps slightly in this. Just my personal thoughts on the matter...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!