Mysql

我應該在多對多表中使用複合 PK 還是代理 PK?

  • December 30, 2015

我有一個數據庫:

DROP TABLE IF EXISTS `books`;

CREATE TABLE `books` (
 `isbn` VARCHAR(255) NOT NULL,
 `title` VARCHAR(255) NULL DEFAULT NULL,
 PRIMARY KEY (`isbn`)
) COMMENT 'Books used at this school';

DROP TABLE IF EXISTS `classes`;

CREATE TABLE `classes` (
 `class_id` INT(10) NOT NULL AUTO_INCREMENT,
 `teacher_id` SMALLINT(5) NULL DEFAULT NULL,
 PRIMARY KEY (`class_id`)
) COMMENT 'Classes at the school';

DROP TABLE IF EXISTS `b_c`;

CREATE TABLE `b_c` (
 `isbn` VARCHAR(255) NOT NULL,
 `class_id` INT(10) NOT NULL,
 PRIMARY KEY (`isbn`)
) COMMENT 'Books to classes';

ALTER TABLE `b_c` ADD FOREIGN KEY (isbn) REFERENCES `books` (`isbn`) 
   ON UPDATE CASCADE;
ALTER TABLE `b_c` ADD FOREIGN KEY (class_id) REFERENCES `classes` (`class_id`) 
   ON UPDATE CASCADE;

我遇到的問題是我想盡可能規範化數據(我不希望將同一關係的多個條目輸入到表中b_c),但我只想儲存絕對相關的數據.

我處理這個問題的第一個想法是b_c為由欄位組成的表創建一個複合主鍵isbnclass_id這將解決表中存在重複關係的問題,但是,我聽到了關於為每個欄位設置唯一標識符的強烈意見像這樣的表中的行。為每一行設置唯一標識符的理由似乎是能夠指定特定行很有用,儘管我沒有看到這會變得有用的情況。有人可以舉個例子嗎?

我聽到的另一個批評是,以這種方式使用複合 PK 會JOIN非常費力。有人可以評論這兩種不同方法的性能嗎?

問題歸結為“id向表中添加欄位是否值得,b_c或者使用複合 PK 是否足以正確表示表booksclasses表之間的關係?

如果您對與該問題不直接相關的設計有任何其他意見,我很想听聽他們的意見,並提前感謝您的幫助。

好吧,看起來你所有的數據都是有意義的,因為你沒有很多數據,而且它們似乎都起到了關鍵或有用屬性的作用。

如果您在 b_c 中的 isbn 上有 PK(根據定義是唯一的),那麼這會將一本書限制為一個類。真的嗎?那時,您可能會爭辯說 class_id 應該只是 book 表的屬性而您甚至不需要 b_c 表的設計。

由於您已經在 b_c 上進行了 PK,因此我認為不需要代理鍵。即使您要擴展為 isbn 上的複合主鍵,class_id 以允許一本書有多個類,我真的不認為需要額外的代理唯一鍵。無論如何,它只是一個替代的唯一鍵,我可能不會將其作為主鍵,也可能不會在連接中使用它(連接到連結表作為外鍵並不是很常見,因為它們通常是由他們的父母或孩子辨識為基於該關係的集合的一部分)

這就是我要做的:

DROP TABLE IF EXISTS `books`;

CREATE TABLE `books` (
 `book_id` INT(10) NOT NULL AUTO_INCREMENT,
 `isbn` VARCHAR(255) NOT NULL,
 `title` VARCHAR(255) NULL DEFAULT NULL,
 PRIMARY KEY (`book_id`)
) COMMENT 'Books used at this school';

/* 
 Also consider a unique constraint here on isbn
 Also consider whether to allow NULL isbn when it isn't yet known
*/

DROP TABLE IF EXISTS `classes`;

CREATE TABLE `classes` (
 `class_id` INT(10) NOT NULL AUTO_INCREMENT,
 `teacher_id` SMALLINT(5) NULL DEFAULT NULL,
 PRIMARY KEY (`class_id`)
) COMMENT 'Classes at the school';

DROP TABLE IF EXISTS `b_c`;

CREATE TABLE `b_c` (
 `book_id` INT(10) NOT NULL,
 `class_id` INT(10) NOT NULL,
 PRIMARY KEY (`book_id`, `class_id`) -- note that book is no longer unique by itself
) COMMENT 'Books to classes';

ALTER TABLE `b_c` ADD FOREIGN KEY (book_id) REFERENCES `books` (`book_id`) ON UPDATE CASCADE;
ALTER TABLE `b_c` ADD FOREIGN KEY (class_id) REFERENCES `classes` (`class_id`) ON UPDATE CASCADE;

引用自:https://dba.stackexchange.com/questions/38708