[英]relational database design - normalization and relationships
我是設計數據庫的新手,我不確定我是否在為我的應用程序設計數據庫時正確實現了規范化和關系。
正在設計的應用程序與購物清單和產品一起使用,並將使用如下數據庫:
我已經“嘗試”為數據庫創建兩種不同的設計,試圖推斷哪種設計可能更適合該場景。 一個使用一對多關系,一個多對多關系,兩者都將shopping_list鏈接到產品 :
問題:
關於一對多:鑒於將有數百萬個不同的產品ID, 一對多設計難道不會在assigned_products表中產生大量冗余信息嗎? products表的字段類似於:
________________________________________________ |assigned_p_id | shopping_list_id | product_code | |--------------+------------------+--------------| | 1 | 1 | aa11aab | |--------------+------------------+--------------| | 2 | 1 | zz1bbbb | |--------------+------------------+--------------| | 3 | 2 | aa11aab |
正如你所看到的, aa11aab
重復了兩次,因為其他人創建了一個具有相同項目的購物清單,因此我想知道這種冗余是否會產生數據庫問題,每個重復的product_code會占用多少不必要的空間?
關於多對多:圖表似乎通過使表shopping_list_products存儲id值而不是重復product_code來消除冗余,但是,這會在檢索信息時導致性能損失嗎? 我假設表之間必須進行一些連接 ,以便每個用戶獲得所有購物清單和購物清單中的產品代碼。
一般來說:我的人際關系/規范化可能有任何錯誤嗎? (我是這方面的新手)
以下是從哪里開始的一些建議。
您需要一張表來存儲有關購買的信息。 在數據中你可以看到Wile E Coyote購買了Dyno-might和鋼琴......
CREATE TABLE IF NOT EXISTS `purchase` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`user_id` int unsigned NOT NULL,
`item_id` int unsigned NOT NULL,
`quantity` double DEFAULT 1,
`price` double NOT NULL,
`qwhen` datetime NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`user_id`) REFERENCES user(id) ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY (`product_id`) REFERENCES product(id) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB Comment='Purchases';
purchase data
+----+---------+------------+----------+--------+---------------------+
| id | user_id | product_id | quantity | price | created |
+----+---------+------------+----------+--------+---------------------+
| 1 | 1 | 1 | 1 | 100.00 | 2016-07-02 20:42:13 |
| 1 | 1 | 3 | 1 | 734.23 | 2016-07-02 21:23:40 |
| .. | ....... | .......... | ........ | ...... | ................... |
+----+---------+------------+----------+--------+---------------------+
您還需要一個表來存儲有關產品的信息。 我假設你正在銷售實體產品,所以我添加了ean
, upca
和其他一些可能有幫助的專欄。
CREATE TABLE IF NOT EXISTS `product` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`manufacturer_id` int unsigned NOT NULL,
`ean` int unsigned NOT NULL,
`upca` int unsigned NOT NULL,
`upce` int unsigned NOT NULL,
`name` varchar(100) NOT NULL,
`height` double DEFAULT NULL,
`width` double DEFAULT NULL,
`depth` double DEFAULT NULL,
`weight` double DEFAULT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`manufacturer_id`) REFERENCES manufacturer(id) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB Comment='Item master file';
product data
+----+-----------------+---------------+--------------+--------+------------+--------+-------+-------+--------+
| id | manufacturer_id | ean | upca | upce | name | height | width | depth | weight |
+----+-----------------+---------------+--------------+--------+------------+--------+-------+-------+--------+
| 1 | 1 | 1234567890123 | 123456789012 | 123456 | Dyno-might | 12.0 | 1.0 | 1.0 | 0.5 |
| 2 | 1 | 2345678901234 | 234567890123 | 234567 | UltraLaser | 96.0 | 96.0 | 96.0 | 450.0 |
| 3 | 2 | 3456789012345 | 345678901234 | 345678 | Piano | 36.0 | 60.0 | 72.0 | 375.0 |
| .. | ............... | ............. | ............ | ...... | .......... | ...... | ..... | ..... | ...... |
+----+-----------------+---------------+--------------+--------+------------+--------+-------+-------+--------+
當我們向人們出售產品時,很高興正式地解決它們,所以我們應該有一個有效的稱呼表。 user
表將具有此表的外鍵。
CREATE TABLE IF NOT EXISTS `salutation` (
`id` varchar(5) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB Comment='Salutations';
salutation data
+------+
| id |
+------+
| Mr. |
| Mrs. |
| Miss |
| Ms. |
| Dr. |
| Rev. |
| .... |
+------+
名稱后綴是人名的一部分,因此我們將創建user
表的那一部分並為該表提供外鍵。
CREATE TABLE IF NOT EXISTS `suffix` (
`id` varchar(5) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB Comment='Suffixes';
suffix data
+-----+
| id |
+-----+
| Sr. |
| Jr. |
| II |
| III |
| IV |
| ... |
+-----+
當然,我們有用戶 - 盡管稱他們為客戶可能更合適。
CREATE TABLE IF NOT EXISTS `user` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`facebook_id` int unsigned NOT NULL,
`email` varchar(255) NOT NULL,
`salutation_id` varchar(5) NOT NULL,
`first_name` varchar(50) NOT NULL,
`middle_name` varchar(50) DEFAULT NULL,
`last_name` varchar(50) NOT NULL,
`suffix_id` varchar(5) DEFAULT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`salutation_id`) REFERENCES salutation(id) ON DELETE RESTRICT ON UPDATE CASCADE,
FOREIGN KEY (`suffix_id`) REFERENCES suffix(id) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB Comment='Users';
user data
+----+-------------+------------------------+---------------+------------+-------------+-----------+-----------+
| id | facebook_id | email | salutation_id | first_name | middle_name | last_name | suffix_id |
+----+-------------+------------------------+---------------+------------+-------------+-----------+-----------+
| 1 | 123456789 | coyote_guy32@gmail.com | Mr. | Wile | E | Coyote | NULL |
| .. | ........... | ...................... | ............. | .......... | ........... | ......... | ......... |
+----+-------------+------------------------+---------------+------------+-------------+-----------+-----------+
在這兩種情況下,你基本上都在做同樣的事情。 在第一種情況下,您將shopping_list_id
映射到product_code
,在第二種情況下,您將其映射到product_id
。 無論您使用product_code
還是product_id
它們似乎都是代表product
實體的外鍵。 在這兩種情況下,要到達產品行,您必須使用該字段加入products
表。
作為一般規則,您應該映射兩個id
列(第二個選項),以便在兩種情況下使用整數主鍵完成連接。 這不僅可以提高存儲和索引的效率,還可以使這些連接速度更快。
此外,正如其中一條評論所指出的,您應該將自動增量主鍵添加到shopping_list_products
表中。
另外,對於命名約定,您可能需要考慮始終使用id
命名主鍵。 例如,不是擁有products.product_id
,而是每個表都有products.id
等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.