我记得在播客014中听到Joel Spolsky提到他几乎从未使用过外键(如果我没记错的话)。然而,对我来说,它们对于避免数据库中的重复和后续数据完整性问题非常重要。
人们是否有一些可靠的理由(以避免与Stack Overflow原则一致的讨论)?
编辑:“我还没有创建外键的理由,所以这可能是我真正建立一个外键的第一个理由。”
我记得在播客014中听到Joel Spolsky提到他几乎从未使用过外键(如果我没记错的话)。然而,对我来说,它们对于避免数据库中的重复和后续数据完整性问题非常重要。
人们是否有一些可靠的理由(以避免与Stack Overflow原则一致的讨论)?
编辑:“我还没有创建外键的理由,所以这可能是我真正建立一个外键的第一个理由。”
当前回答
如果您绝对确信底层数据库系统将来不会改变,我将使用外键来确保数据完整性。
但在现实生活中,还有一个完全不使用外键的很好的理由:
您正在开发一个产品,该产品应该支持不同的数据库系统。
如果您正在使用实体框架(Entity Framework),该框架能够连接到许多不同的数据库系统,那么您可能还希望支持“开源免费”的无服务器数据库。并非所有这些数据库都支持外键规则(更新、删除行……)。
这会导致不同的问题:
1)。在创建或更新数据库结构时,可能会遇到错误。可能只有无声错误,因为数据库系统忽略了外键。
2)。如果依赖于外键,则可能在业务逻辑中较少甚至不进行数据完整性检查。现在,如果新的数据库系统不支持这些外键规则,或者只是以不同的方式运行,那么您必须重写业务逻辑。
您可能会问:谁需要不同的数据库系统?当然,不是每个人都能负担得起或想要在他的机器上安装一个完整的SQL-Server。这是软件,需要维护。其他人已经在其他一些DB系统上投入了时间和金钱。无服务器数据库非常适合只有一台机器上的小客户。
没有人知道,所有这些DB系统是如何运行的,但是您的业务逻辑,包括完整性检查,总是保持不变的。
其他回答
它们会使删除记录变得更加麻烦——当其他表中存在外键违反约束的记录时,您就不能删除“主”记录。可以使用触发器进行级联删除。
如果不明智地选择主键,则更改该值将变得更加复杂。例如,如果我有我的“客户”表的PK作为人的名字,并使该键在“订单”表中为FK,如果客户想更改他的名字,那么这是一个巨大的痛苦……但这只是粗制滥造的数据库设计。
我相信使用火密钥的优点大于任何假定的缺点。
Quite often we receive the errors with FK constraints Cannot add or update a child row: a foreign key constraint fails Suppose there are two tables inventory_source and contract_lines, and we are referring inventory_source_id in contract_lines from inventory_source and suppose we want to delete record from inventory_source and the record is already present in contract_lines or we want to delete the PK column from Base table, we get errors for FK constraints, we can avoid it using the steps jotted below.
CREATE TABLE inventory_source (
inventory_source_id int(11) NOT NULL AUTO_INCREMENT,
display_name varchar(40) NOT NULL,
state_id int(11) NOT NULL,
PRIMARY KEY (inventory_source_id),
KEY state_id (state_id),
CONSTRAINT ba_inventory_source_state_fk FOREIGN KEY (state_id) REFERENCES ba_state (state_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE contract_lines(
contract_line_id int(11) NOT NULL AUTO_INCREMENT,
inventory_source_id int(11) NULL ,
PRIMARY KEY (contract_line_id),
UNIQUE KEY contract_line_id (contract_line_id),
KEY AI_contract_line_id (contract_line_id),
KEY contract_lines_inventory_source_fk (inventory_source_id),
CONSTRAINT contract_lines_inventory_source_fk FOREIGN KEY (inventory_source_id) REFERENCES ba_inventory_source (inventory_source_id)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 ;
我们可以采用以下步骤克服它:-
Delete or update the row from the inventory_source will automatically delete or update the matching rows in the contract_lines table and this is known as cascade delete or update. Another way of doing it is setting the column i.e inventory_source_id in the contract_lines table to NULL, when a record corresponding to it is deleted in the inventory_source table. We can restrict the parent table for delete or update in other words one can reject the delete or update operation for the inventory_source table. Attempt to delete or update a primary key value will not be permitted to proceed if there is a related foreign key value in the referenced table.
我一直认为不用它们是懒惰的表现。我被教导应该一直这样做。但后来,我没有听乔尔的讨论。他也许有充分的理由,我不知道。
“它们会使删除记录变得更加麻烦——你不能删除“主”记录,而其他表中的记录中有外键会违反这种约束。”
重要的是要记住,SQL标准定义了删除或更新外键时所采取的操作。 我所知道的是:
ON DELETE RESTRICT - Prevents any rows in the other table that have keys in this column from being deleted. This is what Ken Ray described above. ON DELETE CASCADE - If a row in the other table is deleted, delete any rows in this table that reference it. ON DELETE SET DEFAULT - If a row in the other table is deleted, set any foreign keys referencing it to the column's default. ON DELETE SET NULL - If a row in the other table is deleted, set any foreign keys referencing it in this table to null. ON DELETE NO ACTION - This foreign key only marks that it is a foreign key; namely for use in OR mappers.
这些相同的操作也适用于ON UPDATE。
默认值似乎取决于您使用的sql server。
澄清数据库是一个没有主键或外键的商业数据库示例。
http://www.geekinterview.com/question_details/18869
有趣的是,技术文档花了很大的篇幅来解释表是如何关联的,用什么列来连接它们等等。
换句话说,它们本可以使用显式声明(DRI)连接表,但它们选择不这样做。
因此,澄清数据库充满了不一致,性能不佳。
但我认为它使开发人员的工作更容易,不必编写代码来处理引用完整性,例如在删除或添加之前检查相关行。
我认为,这就是关系数据库中没有外键约束的主要好处。它使开发变得更容易,至少从不顾一切的角度来看是这样。