复合主键与额外的“ID”列之间的区别?
问题的出现原因:
- 主键的值不应该改变,因此通常使用盲目或替代主键。
- 如果作者的名字拼写错误,需要修改数据库中的多行数据和索引引用,工作量巨大。
解决方法:
- 创建一个包含替代主键的作者表,只需修改一行数据,无需更改索引。
- 在数据库中使用单数形式的表名。
代码示例:
CREATE TABLE Author ( author_id INT PRIMARY KEY AUTO_INCREMENT, author_name VARCHAR(100) ); CREATE TABLE Book ( book_id INT PRIMARY KEY AUTO_INCREMENT, book_name VARCHAR(100), author_id INT, FOREIGN KEY (author_id) REFERENCES Author(author_id) );
原则上,我们不希望主键的值发生变化,这就是为什么使用盲目或替代主键的原因。
假设您创建了一个包含作者作为主键的图书表。
假设您在大约一年后发现拼写错误的“Ray Bradbury”。或者更糟糕的是,您拼写错误的是“Rachael Bloom”。想象一下,您需要修改多少个数据库行来纠正拼写错误。想象一下,需要更改多少个索引引用。
然而,如果您有一个具有替代键的作者表,您只需要更正一行。不需要更改索引。
最后,数据库表名通常是单数形式(Book),而不是复数形式(Books)。
关于单数和复数形式的争论有不同的主观观点,这不适合在这里讨论。
当您说替代键时,您是指使用ID/ISBN吗?
我的意思是一个与图书无关的主键。通常,它是一个从零开始递增的整数,每添加一行递增一次。我称它们为盲目的键。
在ER建模中,单数是被接受的约定。在面向对象编程中,类名是单数形式,即使它们可以被实例化多次。但我同意这在一定程度上是主观的,使用不同的约定肯定不是一个致命的错误。
我同意Gilbert的观点。我几乎总是在有些其他字段可以作为主键的情况下添加一些行标识符(通常是一个int identity列)。看看这个例子-哪个更容易更新用户,其中用户名= 'jr33s22dt6uwwdrrws33ww',还是更新用户,其中用户id = 4?
另一个想法-如果您拼错了某个东西(Rachael Boolm)并且要重命名它,如果它是主键的一部分-如果它正确存在怎么办?您必须立即修复它。而如果它不是主键的一部分,您可以先更新它,然后以后再检查它,而不是实时检查。并且凭经验-很有可能您会得到两本相同的书。
我发现验证语句是否正确更容易,无论是手动验证还是调试代码时,当它们涉及具有语义意义的字段时,例如作者和标题。现在在书的示例中,的确作者+标题的组合可能不适合于其他表的引用等方面。而且ISBN不一定具有我提到的好处(至少在一种缩减的方式中)。但是一般来说,如果没有好的理由发明一个对我没有意义的标识符,我宁愿使用一个对我有意义的标识符。
复合主键和额外的"ID"列之间的差异是什么?这个问题的出现是因为复合主键可能会占用较多的空间,而额外的"ID"列可以减小其他表和索引的大小。解决方法是在书籍表中添加一个唯一的整数列作为主键,并将其作为外键引用。同时,确保复合主键仍然是唯一的,以防止重复数据的插入。
如果{Author, Title, Edition}
可以唯一标识一本书,那么以下情况成立:
- 它是一个超键 -- 可以唯一标识一个元组(行)。
- 它是不可约的 -- 移除任何一个列都不会使它成为一个键。
- 它是一个候选键 -- 不可约的超键是一个候选键。
现在考虑一下ID(整数)
我可以推断出Book
表的主键会出现在其他一些表中作为外键,并且还会出现在一些索引中。因此,它将在每个表中占用相当多的空间 -- 假设每个表有三列 x 40个字符(或其他...)-- 以及匹配的索引。
为了使这些"其他"表和索引更小,我可以在Book
表中添加一个唯一的整数列作为主键,该主键将被引用为外键。例如:
alter table Book add BookID integer not null identity;
由于BookID
也是唯一的,Book
表现在有两个候选键。
现在我可以选择将BookID
作为主键。
alter table Book add constraint pk_Book primary key (BookID);
然而,{Author,Title,Edition}
仍然必须保持为唯一的键,以防止出现如下情况:
BookID Author Title Edition
-----------------------------------------------
1 C.J.Date Database Design 1
2 C.J.Date Database Design 1
总结一下,添加BookID
并将其选择为主键并没有阻止{Author, Title, Edition}
成为(候选)键。它仍然必须具有自己的唯一约束,并且通常需要相应的索引。
还要注意,从设计的角度来看,这个决策是在"物理层面"上进行的。通常,在逻辑设计层面上,这个"ID"并不存在 -- 它是在考虑列大小和索引时引入的。因此,物理模式是从逻辑模式中派生出来的。根据数据库的大小、RDBMS和使用的硬件,这种大小推理可能没有可测量的影响 -- 因此,使用{Author, Title, Edition}
作为主键可能是完全良好的设计 -- 直到有其他证据证明不是这样。