鍍金池/ 問答/HTML5  Java  數(shù)據(jù)庫/ 互聯(lián)網(wǎng)開發(fā)中不用外鍵到底是個什么意思?

互聯(lián)網(wǎng)開發(fā)中不用外鍵到底是個什么意思?

都說互聯(lián)網(wǎng)開發(fā)盡量不用外鍵,那么這里的不用外鍵到底代表的啥意思呢?
1.這里有一層意思很明確:
不用外鍵約束。比如刪除一張表中的數(shù)據(jù)時,如果要級聯(lián)刪除另一張表中關聯(lián)的數(shù)據(jù),以往是由數(shù)據(jù)庫來級聯(lián)約束的,現(xiàn)在應該將其移到程序中由程序來保持數(shù)據(jù)的一致性。

2.另外一層意思:
外鍵的定義就是在一個表中的字段是另外一張表中的主鍵。如果僅按照"不使用外鍵"這幾個字的字面理解,就是要把外鍵字段抽取出來放在一張中間表中。簡單說就是都當成多對多來處理。
比如

用戶(userid,username)  
訂單(orderid,totalPrice,userid)

問題1:這里useid就是一個外鍵,如果不用外鍵,是否就要設計成這樣?

用戶(userid,username)  
訂單(orderid,totalPrice)
用戶-訂單中間表(userid,orderid)

問題2:如果是這樣,假如一張表有多個外鍵,豈不是要有很多中間表?

翻遍了百度都是說不要用外鍵,而不是說不用外鍵約束,所以讓我很疑惑,希望各位大大解惑。謝謝了!

回答
編輯回答
喵小咪
都說互聯(lián)網(wǎng)開發(fā)盡量不用外鍵,那么這里的不用外鍵到底代表的啥意思呢?

這里的外鍵指的數(shù)據(jù)庫的外鍵約束。

不用外鍵約束。比如刪除一張表中的數(shù)據(jù)時,如果要級聯(lián)刪除另一張表中關聯(lián)的數(shù)據(jù),以往是由數(shù)據(jù)庫來級聯(lián)約束的,現(xiàn)在應該將其移到程序中由程序來保持數(shù)據(jù)的一致性。

是的。外鍵這種約束關系不在由數(shù)據(jù)庫幫你保持維護,由應用程序維護。

外鍵的定義就是在一個表中的字段是另外一張表中的主鍵。如果僅按照"不使用外鍵"這幾個字的字面理解,就是要把外鍵字段抽取出來放在一張中間表中。簡單說就是都當成多對多來處理。

不是的。怎么建表還是和原來一樣,只不過在需要建立外鍵約束的地方不建立外鍵約束而已。

比如我們原來建表語句是這樣的:

CREATE TABLE `user` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `user_name` varchar(50) NOT NULL DEFAULT '' COMMENT '用戶名',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `total_price` decimal(10,2) NOT NULL DEFAULT '0.00',
  `user_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `for_indx_user_id` (`user_id`),
  CONSTRAINT `for_indx_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

不是用外鍵約束后:

CREATE TABLE `user` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `user_name` varchar(50) NOT NULL DEFAULT '' COMMENT '用戶名',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `total_price` decimal(10,2) NOT NULL DEFAULT '0.00',
  `user_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

不適用外鍵約束后,為了加快查詢我們通常會給不建立外鍵約束的字段添加一個索引。

CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `total_price` decimal(10,2) NOT NULL DEFAULT '0.00',
  `user_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

如果你理解了,你下面的問題就自然而然不存在了。

避免使用外鍵,可以在插入數(shù)據(jù)時通過程序維持約束關系。

使用外鍵約束優(yōu)點:

  • 外鍵可節(jié)省開發(fā)量
  • 外鍵能約束數(shù)據(jù)有效性,非法數(shù)據(jù)不能插入

使用外鍵約束缺點:

  • 有額外開銷
  • 主鍵表被鎖定時,會引發(fā)外鍵表也被鎖
  • 刪除主鍵表的數(shù)據(jù)時,需先刪除外鍵表的數(shù)據(jù)
  • 修改外鍵表字段時,需重建外鍵約束

實際開發(fā)中,一般不會建立外鍵約束。

2018年4月15日 17:26
編輯回答
呆萌傻

就是不用數(shù)據(jù)庫的外鍵啊,建表的時候不用CONSTRAINT就行了,之后的該怎么寫就怎么寫,要不要多建一張中間表就看具體業(yè)務需不需要

2017年3月2日 16:42
編輯回答
我甘愿

我看了一下,網(wǎng)上大部分說的“外鍵”就是指的“外鍵約束”。在代碼中維護關聯(lián)的不應該叫外鍵,外鍵這種說法應該僅限于數(shù)據(jù)庫。

這個帖子里講的很清楚了,性能問題、死鎖問題等,這些都是“外鍵約束”才有的問題。
https://www.zhihu.com/questio...

2017年2月23日 23:50