InnoDB外鍵使用小結

USE `wfc_database`;
#  主表(也能夠稱做:被參照表、referenced table、outTable)
ALTER TABLE `app` ENGINE=INNODB;
#  從表(也能夠稱做:參照表、外表、referencing tableALTER TABLE `app_version` ENGINE=INNODB;
# 一個 【應用 】能夠有多個【應用版本】
# 所以 app 和 app_version 是 1:n 的關係 (一個 app_id 對應有多個 av_app_id)
# app_id是 app表 的主鍵, av_app_id是 app_version表 的索引

# app_version數據訂正(在 app_version表中刪除 app已經沒有的 app_id)
DELETE FROM `app_version` WHERE av_app_id NOT IN ( SELECT app_id FROM app);
# 此步驟極爲重要,不然沒法添加外鍵(從表中存在主表中沒有的外鍵id是不容許的)

# app_version添加外鍵
ALTER TABLE `app_version`
ADD CONSTRAINT fk_av_app_id                
FOREIGN KEY (av_app_id)
REFERENCES `app` (app_id)
ON DELETE CASCADE ON UPDATE CASCADE;

# 創建外鍵的前提:
  被約束字段與外鍵的數據類型必須相同
  被約束字段須要設置爲索引,外鍵須要設置爲 PRIMARY
  外鍵做用: 使兩張表造成關聯,外鍵只能引用從表中的列的值!
  指定從表關鍵字: foreign key (列名)
  引用外鍵關鍵字: references <外鍵表名> (外鍵列名)
# 事件觸發(級聯操做)限制 : on deleteon update
  可設參數 cascade (跟隨外鍵改動) ,強烈推薦,可以保存數據一致性
  restrict (限制主表中的外鍵改動)
  [默認] no action 

# 若是以上語句在建立過程當中有報以下錯誤
  Can not create table 'd91.#sql-197e_18b4' (errno: 150)
# 請把 av_app_id 和 app_id 的字段類型設置爲徹底相同
  也就是約束字段的 類型、長度、有無符號、是否爲空、默認值 要設置跟外鍵相同
  對於此次的場景,我把 app_id 和 av_app_id 都設置爲 INT(10) , UNSIGNED,NOT NULL
  確保外鍵的名字沒有和已經存在的 鍵值/索引名 重名

# 補充,若是要刪除外鍵約束能夠這麼作
  alter table 表名 drop foreign key 外鍵約束名稱;
# 好比,要刪掉剛剛建立的外鍵,你能夠
  ALTER TABLE `app_version` DROP FOREIGN KEY fk_av_app_id ;

# --------------------- InnoDB外鍵知識 ------------------------- #

方法一:  
定義數據表
  假如某個電腦生產商,它的數據庫中保存着整機和配件的產品信息。用來保存整機產品信息的表叫作 Pc;用來保存配件供貨信息的表叫作Parts。
  在Pc表中有一個字段,用來描述這款電腦所使用的CPU型號;
  在Parts 表中相應有一個字段,描述的正是CPU的型號,咱們能夠把它想成是所有CPU的型號列表。
  很顯然,這個廠家生產的電腦,其使用的CPU必定是供貨信息表(parts)中存在的型號。這時,兩個表中就存在一種約束關係(constraint)——Pc表中的CPU型號受到Parts 表中型號的約束。

  首先咱們來建立 parts 表:
CREATE TABLE parts (
... 字段定義 ...,
model VARCHAR(20) NOT NULL,
... 字段定義 ...
);
接下來是Pc表:                   
CREATE TABLE pc (
... 字段定義 ...,
cpumodel VARCHAR(20) NOT NULL,
... 字段定義 ...
};
  設置索引
  若要設置MySQL外鍵,在 參照表 [外表] (referencing table,即Pc表) 和被參照表 [主表] (referenced table,即parts表) 中,相對應的兩個字段必須都設置索引(index)。

  對Parts表:
  ALTER TABLE parts ADD INDEX idx_model (model);
  這句話的意思是,爲 parts 表增長一個索引,索引創建在 model 字段上,給這個索引發個名字叫idx_model。

  對Pc表也相似:
  ALTER TABLE pc ADD INDEX idx_cpumodel (cpumodel);
  事實上這兩個索引能夠在建立表的時候就設置。這裏只是爲了突出其必要性。

  定義外鍵
  下面爲兩張表之間創建前面所述的那種「約束」。由於pc的CPU型號必須參照parts表中的相應型號,因此咱們將Pc表的cpumodel字段設置爲「外鍵」(FOREIGN KEY),即這個鍵的參照值來自於其餘表。

ALTER TABLE pc ADD CONSTRAINT fk_cpu_model
FOREIGN KEY (cpumodel)
REFERENCES parts(model); 

  第一行是說要爲Pc表設置MySQL外鍵,給這個外鍵起一個名字叫作fk_cpu_model;第二行是說將本表的cpumodel字段設置爲外鍵;第三行是說這個外鍵受到的約束來自於Parts表的model字段。

  這樣,咱們的外鍵就能夠了。若是咱們試着CREATE一臺Pc,它所使用的CPU的型號是Parts表中不存在的,那麼MySQL會禁止這臺PC被CREATE出來。

  級聯操做
  考慮如下這種狀況:
  技術人員發現,一個月以前輸入到 parts 表中的某個系列的 cpu (可能有不少款)的型號全都輸錯了一個字母,如今須要改正。咱們但願的是,當 parts 表中那些 Referenced Column 有所變化時,相應表中的 Referencing Column 也能自動更正。
  能夠在定義MySQL外鍵的時候,在最後加入這樣的關鍵字:
  ON UPDATE CASCADE; 即在主表更新時,子表(們)產生連鎖更新動做,彷佛有些人喜歡把這個叫「級聯」操做。:)
  若是把這語句完整的寫出來,就是:
# 例子一
ALTER TABLE pc ADD CONSTRAINT fk_cpu_model
FOREIGN KEY (cpumodel)
REFERENCES parts(model)
ON UPDATE CASCADE; 

  除了 CASCADE 外,還有 RESTRICT(禁止主表變動)、SET NULL(子表相應字段設置爲空)等操做。
  延伸閱讀

  外鍵(Foreign Key)
  若是公共關鍵字在一個關係中是主關鍵字,那麼這個公共關鍵字被稱爲另外一個關係的外鍵。因而可知,外鍵表示了兩個關係之間的聯繫。以另外一個關係的外鍵做主關鍵字的表被稱爲主表,具備此外鍵的表被稱爲主表的從表。外鍵又稱做外關鍵字。

  外鍵的做用:
  保持數據一致性,完整性,主要目的是控制存儲在外鍵表中的數據。 使兩張表造成關聯,外鍵只能引用外表中的列的值!

方法二:
創建外鍵的前提: 本表的列必須與外鍵類型相同(外鍵必須是外表主鍵)。
外鍵做用: 使兩張表造成關聯,外鍵只能引用外表中的列的值!
指定主鍵關鍵字: foreign key(列名)
引用外鍵關鍵字: references <外鍵表名>(外鍵列名)
事件觸發限制: on delete和on update , 可設參數cascade(跟隨外鍵改動), restrict(限制外表中的外鍵改動),set Null(設空值),set Default(設默認值),[默認]no action 

例如:
outTable表 主鍵 id 類型 int
建立含有外鍵的表: 

create table temp(
id int,
name char(20),
foreign key(id) references outTable(id)
on delete cascade on update cascade); 

建立後修改表:
alter table temp add constraint  foreign key(id) references outTable(id) on delete cascade on update cascade; 

說明:把id列設爲外鍵,參照外表outTable的id列,當外鍵的值刪除本表中對應的列刪除;當外鍵的值改變本表中對應的列值改變。在使用alter中constraint是針對使用外鍵的狀況。
這種主外鍵的級聯操做在mysql中只支持InnoDB類型。要設置爲該類型要在mysql中的配置文件中改動默認不支持InnoDB爲支持,可輸入命令查看是否支持:

mysql > show variables like "have%";
若是不支持中止mysql,打開my.ini配置文件找到skip-innodb,前面加#,重啓mysql,而後修改主外鍵兩表類型:

mysql > alter table xxx ENGINE = InnoDB;
最後在命令中輸入上述建立外鍵的方法。 不過,若是你的業務不須要使用到事務,那麼使用myisam是最佳考慮, 由於myisam不支持事務,有比較好的性能。 可是若是你的業務必需要使用到事務,也就是說對數據一致性要求很高的話,須要使用到INODB,因爲INODB要使用到鎖,所以它的併發能力就差一些,所以性能方面也會差一些。

若是要刪除外鍵約束可以使用以下命令:
mysql > alter table ss_accesscode drop foreign key 外鍵約束名稱;

注:添加外鍵約束時若沒有指定外鍵約束的名稱,則系統會自動添加外鍵約束名:表名_ibfk_n(表示第n個外鍵約束)。好比咱們建立外鍵時就省略了外鍵線束名稱。
相關文章
相關標籤/搜索