我记得在播客014中听到Joel Spolsky提到他几乎从未使用过外键(如果我没记错的话)。然而,对我来说,它们对于避免数据库中的重复和后续数据完整性问题非常重要。
人们是否有一些可靠的理由(以避免与Stack Overflow原则一致的讨论)?
编辑:“我还没有创建外键的理由,所以这可能是我真正建立一个外键的第一个理由。”
我记得在播客014中听到Joel Spolsky提到他几乎从未使用过外键(如果我没记错的话)。然而,对我来说,它们对于避免数据库中的重复和后续数据完整性问题非常重要。
人们是否有一些可靠的理由(以避免与Stack Overflow原则一致的讨论)?
编辑:“我还没有创建外键的理由,所以这可能是我真正建立一个外键的第一个理由。”
当前回答
它们会使删除记录变得更加麻烦——当其他表中存在外键违反约束的记录时,您就不能删除“主”记录。可以使用触发器进行级联删除。
如果不明智地选择主键,则更改该值将变得更加复杂。例如,如果我有我的“客户”表的PK作为人的名字,并使该键在“订单”表中为FK,如果客户想更改他的名字,那么这是一个巨大的痛苦……但这只是粗制滥造的数据库设计。
我相信使用火密钥的优点大于任何假定的缺点。
其他回答
在我参与的一个项目中,经常存在隐式关系而不是显式关系,这样可以在同一列上连接多个表。
请看下面的表格
地址
AddressId (PK) EntityId EntityType 城市 状态 国家 等。
EntityType的值可能是Employee、Company、Customer, EntityId指的是您感兴趣的表的主键。
我真的不认为这是最好的方法,但它对这个项目有效。
“在添加记录之前,检查对应的记录是否存在于另一个表中”是业务逻辑。
这里有一些你不希望在数据库中使用它的原因:
If the business rules change, you have to change the database. The database will need to recreate the index in a lot of cases and this is slow on large tables. (Changing rules include: allow guests to post messages or allow users to delete their account despite having posted comments, etc). Changing the database is not as easy as deploying a software fix by pushing the changes to the production repository. We want to avoid changing the database structure as much as possible. The more business logic there is in the database the more you increase the chances of needing to change the databae (and triggering re-indexing). TDD. In unit tests you can substitute the database for mocks and test the functionality. If you have any business logic in your database, you are not doing complete tests and would need to either test with the database or replicate the business logic in code for testing purposes, duplicating the logic and increasing the likelyhood of the logic not working in the same way. Reusing your logic with different data sources. If there is no logic in the database, my application can create objects from records from the database, create them from a web service, a json file or any other source. I just need to swap out the data mapper implementation and can use all my business logic with any source. If there is logic in the database, this isn't possible and you have to implement the logic at the data mapper layer or in the business logic. Either way, you need those checks in your code. If there's no logic in the database I can deploy the application in different locations using different database or flat-file implementations.
From my experience its always better to avoid using FKs in Database Critical Applications. I would not disagree with guys here who say FKs is a good practice but its not practical where the database is huge and has huge CRUD operations/sec. I can share without naming ... one of the biggest investment bank of doesn't have a single FK in databases. These constrains are handled by programmers while creating applications involving DB. The basic reason is when ever a new CRUD is done it has to effect multiple tables and verify for each inserts/updates, though this won't be a big issue for queries affecting single rows but it does create a huge latency when you deal with batch processing which any big bank has to do as daily tasks.
最好避免fk,但它的风险必须由程序员来处理。
在这里回答问题的许多人都过于关注通过引用约束实现的引用完整性的重要性。在具有引用完整性的大型数据库上工作性能不佳。Oracle似乎特别不擅长级联删除。我的经验法则是,应用程序永远不应该直接更新数据库,而应该通过存储过程更新。这将代码库保存在数据库中,并意味着数据库保持其完整性。
在许多应用程序可能正在访问数据库的地方,由于引用完整性约束确实会出现问题,但这取决于控件。
还有一个更广泛的问题,应用程序开发人员可能有非常不同的需求,而数据库开发人员可能并不那么熟悉。
验证外键约束需要一些CPU时间,因此有些人省略外键以获得额外的性能。