一、概念:
??? 1、主鍵(primary key)? 能夠唯一標(biāo)識表中某一行的屬性或?qū)傩越M。一個表只能有一個主鍵,但可以有多個候選索引。主鍵常常與外鍵構(gòu)成參照完整性約束,防止出現(xiàn)數(shù)據(jù)不一致。主鍵可以保證記錄的唯一和主鍵域非空,數(shù)據(jù)庫管理系統(tǒng)對于主鍵自動生成唯一索引,所以主鍵也是一個特殊的索引 。
??? 2、外鍵(foreign key) ?是用于建立和加強(qiáng)兩個表數(shù)據(jù)之間的鏈接的一列或多列。外鍵約束主要用來維護(hù)兩個表之間數(shù)據(jù)的一致性。 簡言之,表的外鍵就是另一表的主鍵,外鍵將兩表聯(lián)系起來。一般情況下,要刪除一張表中的主鍵必須首先要確保其它表中的沒有相同外鍵(即該表中的主鍵沒有一個外鍵和它相關(guān)聯(lián))。
??? 3、索引(index) ? 是用來快速地尋找那些具有特定值的記錄。主要是為了檢索的方便,是為了加快訪問速度, 按一定的規(guī)則創(chuàng)建的,一般起到排序作用。所謂唯一性索引 ,這種索引和前面的“普通索引”基本相同,但有一個區(qū)別:索引列的所有值都只能出現(xiàn)一次,即必須唯一。
??? 總結(jié):
主鍵一定是唯一性索引,唯一性索引并不一定就是主鍵。
?一個表中可以有多個唯一性索引,但只能有一個主鍵。
主鍵列不允許空值,而唯一性索引列允許空值。
主鍵可以被其他字段作外鍵引用,而索引不能作為外鍵引用。
二、具體介紹:
??? 1、主鍵:
?????主鍵是數(shù)據(jù)表的唯一索引,比如學(xué)生表里有學(xué)號和姓名,姓名可能有重名的,但學(xué)號確是唯一的,你要從學(xué)生表中搜索一條紀(jì)錄如查找一個人,就只能根據(jù)學(xué)號去查找,這才能找出唯一的一個,這就是主鍵;如:idint(10) not null primary key auto_increment ;自增長的類型 ;
??? 2、外鍵:
?????定義數(shù)據(jù)表
假如某個電腦生產(chǎn)商,它的數(shù)據(jù)庫中保存著整機(jī)和配件的產(chǎn)品信息。用來保存整機(jī)產(chǎn)品信息的表叫做Pc;用來保存配件供貨信息的表叫做Parts。
在Pc表中有一個字段,用來描述這款電腦所使用的CPU型號;
在Parts 表中相應(yīng)有一個字段,描述的正是CPU的型號,我們可以把它想成是全部CPU的型號列表。
很顯然,這個廠家生產(chǎn)的電腦,其使用的CPU一定是供貨信息表(parts)中存在的型號。這時,兩個表中就存在一種約束關(guān)系(constraint)——Pc表中的CPU型號受到Parts表中型號的約束。
首先我們來創(chuàng)建 parts 表:
CREATE TABLE parts ( ... 字段定義 ..., model VARCHAR(20) NOT NULL, ... 字段定義 ... );
?
接下來是pc表:
CREATE TABLE pc ( ... 字段定義 ..., cpumodel VARCHAR(20) NOT NULL, ... 字段定義 ... };
設(shè)置索引
若要設(shè)置外鍵,在參照表(referencing table,即Pc表) 和被參照表 (referencedtable,即parts表) 中,相對應(yīng)的兩個字段必須都設(shè)置索引(index)。
對Parts表:
ALTER TABLE parts ADD INDEX idx_model (model);
這句話的意思是,為 parts 表增加一個索引,索引建立在 model字段上,給這個索引起個名字叫idx_model。
對Pc表也類似:
ALTER TABLE pc ADD INDEX idx_cpumodel (cpumodel);
事實(shí)上這兩個索引可以在創(chuàng)建表的時候就設(shè)置。這里只是為了突出其必要性。
定義外鍵
下面為兩張表之間建立前面所述的那種“約束”。因?yàn)閜c的CPU型號必須參照parts表中的相應(yīng)型號,所以我們將Pc表的cpumodel字段設(shè)置為“外鍵”(FOREIGNKEY),即這個鍵的參照值來自于其他表。
ALTER TABLE pc ADD CONSTRAINT fk_cpu_model FOREIGN KEY (cpumodel) REFERENCES parts(model);
第一行是說要為Pc表設(shè)置外鍵,給這個外鍵起一個名字叫做fk_cpu_model;第二行是說將本表的cpumodel字段設(shè)置為外鍵;第三行是說這個外鍵受到的約束來自于Parts表的model字段。
這樣,我們的外鍵就可以了。如果我們試著CREATE一臺Pc,它所使用的CPU的型號是Parts表中不存在的,那么MySQL會禁止這臺PC被CREATE出來。
級聯(lián)操作
考慮以下這種情況:
技術(shù)人員發(fā)現(xiàn),一個月之前輸入到 parts 表中的某個系列的 cpu(可能有很多款)的型號全都輸錯了一個字母,現(xiàn)在需要改正。我們希望的是,當(dāng) parts 表中那些 Referenced Column有所變化時,相應(yīng)表中的 Referencing Column 也能自動更正。
可以在定義外鍵的時候,在最后加入這樣的關(guān)鍵字:
ON UPDATE CASCADE;即在主表更新時,子表(們)產(chǎn)生連鎖更新動作,似乎有些人喜歡把這個叫“級聯(lián)”操作。:)
如果把這語句完整的寫出來,就是:
ALTER TABLE pc ADD CONSTRAINT fk_cpu_model FOREIGN KEY (cpumodel) REFERENCES parts(model) ON UPDATE CASCADE;
?
除了 CASCADE 外,還有 RESTRICT(禁止主表變更)、SET NULL(子表相應(yīng)字段設(shè)置為空)等操作
索引:
?????索引用來快速地尋找那些具有特定值的記錄,所有MySQL索引都以B-樹的形式保存。如果沒有索引,執(zhí)行查詢時MySQL必須從第一個記錄開始掃描整個表的所有記錄,直至找到符合要求的記錄。表里面的記錄數(shù)量越多,這個操作的代價就越高。如果作為搜索條件的列上已經(jīng)創(chuàng)建了索引,MySQL無需掃描任何記錄即可迅速得到目標(biāo)記錄所在的位置。如果表有1000個記錄,通過索引查找記錄至少要比順序掃描記錄快100倍。
??????假設(shè)我們創(chuàng)建了一個名為people的表:
CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL );
然后,我們完全隨機(jī)把1000個不同name值插入到people表。 在數(shù)據(jù)文件中name列沒有任何明確的次序。如果我們創(chuàng)建了name列的索引,MySQL將在索引中排序name列 對于索引中的每一項(xiàng),MySQL在內(nèi)部為它保存一個數(shù)據(jù)文件中實(shí)際記錄所在位置的“指針”。因此,如果我們要查找name等于“Mike”記錄的 peopleid(SQL命令為“SELECTpeopleid FROM people WHEREname='Mike';”),MySQL能夠在name的索引中查找“Mike”值,然后直接轉(zhuǎn)到數(shù)據(jù)文件中相應(yīng)的行,準(zhǔn)確地返回該行的 peopleid(999)。在這個過程中,MySQL只需處理一個行就可以返回結(jié)果。如果沒有“name”列的索引,MySQL要掃描數(shù)據(jù)文件中的所有 記錄,即1000個記錄!顯然,需要MySQL處理的記錄數(shù)量越少,則它完成任務(wù)的速度就越快。
索引的類型 MySQL提供多種索引類型供選擇: 普通索引 這是最基本的索引類型,而且它沒有唯一性之類的限制。普通索引可以通過以下幾種方式創(chuàng)建:
創(chuàng)建索引,例如:CREATE?INDEX?<索引的名字>?ON?tablename?(列的列表);
修改表,例如:ALTER?TABLE?tablename?ADD?INDEX?[索引的名字]?(列的列表);?
創(chuàng)建表的時候指定索引,例如:CREATE?TABLE?tablename?(?[...],?INDEX?[索引的名字]?(列的列表)?);
唯一性索引 這種索引和前面的“普通索引”基本相同,但有一個區(qū)別:索引列的所有值都只能出現(xiàn)一次,即必須唯一。唯一性索引可以用以下幾種方式創(chuàng)建:
創(chuàng)建索引,例如:CREATE?UNIQUE?INDEX?<索引的名字>?ON?tablename?(列的列表);?
修改表,例如:ALTER?TABLE?tablename?ADD?UNIQUE?[索引的名字]?(列的列表);?
創(chuàng)建表的時候指定索引,例如:CREATE?TABLE?tablename?(?[...],?UNIQUE?[索引的名字]?(列的列表)?);
主鍵 主鍵是一種唯一性索引,但它必須指定為“PRIMARYKEY ”。如果你曾經(jīng)用過AUTO_INCREMENT 類型的列,你可能已經(jīng)熟悉主鍵之類的概念了。主鍵一般在創(chuàng)建表的時候指定,例如:
????? “CREATETABLE tablename ( [...], PRIMARY?KEY ?(列的列表) );”
但是,我們也可以通過修改表的方式加入主鍵,例如:
????? “ALTER TABLE tablename ADD PRIMARY KEY(列的列表); ”
每個表只能有一個主鍵。 單列索引與多列索引 索引可以是單列索引,也可以是多列索引。下面我們通過具體的例子來說明這兩種索引的區(qū)別。假設(shè)有這樣一個people表:
CREATE?TABLE?people?
(?peopleid?SMALLINT?NOT?NULL?AUTO_INCREMENT,?firstname?CHAR(50)?NOT?NULL,?lastname?CHAR(50)?NOT?NULL,?age?SMALLINT?NOT?NULL,?townid?SMALLINT?NOT?NULL,PRIMARY?KEY?(peopleid)?);
??? 假如:這個表中有四個名字為“Mike”的人(其中兩個姓Sullivans,兩個姓McConnells),有兩個年齡為17歲的人,還有一個名字與眾不同的Joe Smith。 ??? 這個表的主要用途是根據(jù)指定的用戶姓、名以及年齡返回相應(yīng)的peopleid。例如,我們可能需要查找姓名為MikeSullivan、年齡17歲用戶的 peopleid
(SQL命令為SELECT peopleid FROM people WHEREfirstname='Mike' AND lastname='Sullivan' AND age=17;)。
由于我們不想讓MySQL每次執(zhí)行查詢就去掃描整個表,這里需要考慮運(yùn)用索引。 首先,我們可以考慮在單個列上創(chuàng)建索引,比如firstname、lastname或者age列。如果我們創(chuàng)建firstname列的索引 (ALTERTABLE people ADD INDEX firstname(firstname);),MySQL將通過這個索引迅速把搜索范圍限制到那些firstname='Mike'的記錄,然后再在這 個“中間結(jié)果集”上進(jìn)行其他條件的搜索:它首先排除那些lastname不等于“Sullivan”的記錄,然后排除那些age不等于17的記錄。當(dāng)記錄滿足所有搜索條件之后,MySQL就返回最終的搜索結(jié)果。 ??? 由于建立了firstname列的索引,與執(zhí)行表的完全掃描相比,MySQL的效率提高了很多,但我們要求MySQL掃描的記錄數(shù)量仍舊遠(yuǎn)遠(yuǎn)超過了實(shí)際所需要的。雖然我們可以刪除firstname列上的索引,再創(chuàng)建lastname或者age列的索引,但總地看來,不論在哪個列上創(chuàng)建索引搜索效率仍舊相似。 ??? 為了提高搜索效率,我們需要考慮運(yùn)用多列索引。如果為firstname、lastname和age這三個列創(chuàng)建一個多列索引,MySQL只需一次檢索就能夠找出正確的結(jié)果!下面是創(chuàng)建這個多列索引的SQL命令:
ALTER?TABLE?people?ADD?INDEX?fname_lname_age?(firstname,lastname,age);
??? 由于索引文件以B-樹格式保存,MySQL能夠立即轉(zhuǎn)到合適的firstname,然后再轉(zhuǎn)到合適的lastname,最后轉(zhuǎn)到合適的age。在沒有掃描數(shù)據(jù)文件任何一個記錄的情況下,MySQL就正確地找出了搜索的目標(biāo)記錄! ??? 那么,如果在firstname、lastname、age這三個列上分別創(chuàng)建單列索引,效果是否和創(chuàng)建一個firstname、lastname、 age的多列索引一樣呢?答案是否定的,兩者完全不同。當(dāng)我們執(zhí)行查詢的時候,MySQL只能使用一個索引。如果你有三個單列的索引,MySQL會試圖選擇一個限制最嚴(yán)格的索引。但是,即使是限制最嚴(yán)格的單列索引,它的限制能力也肯定遠(yuǎn)遠(yuǎn)低于firstname、lastname、age這三個列上的多列 索引。 最左前綴 ??? 多列索引還有另外一個優(yōu)點(diǎn),它通過稱為最左前綴 (LeftmostPrefixing)的概念體現(xiàn)出來。繼續(xù)考慮前面的例子,現(xiàn)在我們有一個firstname、lastname、age列上的多列索引,我們稱這個索引為fname_lname_age。當(dāng)搜索條件是以下各種列的組合時,MySQL將使用fname_lname_age索引:
firstname,lastname?age,?firstname?lastname,?firstname
??? 從另一方面理解,它相當(dāng)于我們創(chuàng)建了(firstname,lastname,age)、(firstname,lastname)以及(firstname)這些列組合上的索引。下面這些查詢都能夠使用這個fname_lname_age索引:
SELECT?peopleid?FROM?people?WHERE?firstname='Mike'?AND?lastname='Sullivan'?AND?age='17';
SELECT?peopleid?FROM?people?WHERE?firstname='Mike'?AND?lastname='Sullivan';?
SELECT?peopleid?FROM?people?WHERE?firstname='Mike';The?following?queries?cannot?use?the?index?at?all:?SELECT?peopleid?FROM?people?WHERE?lastname='Sullivan';?
SELECT?peopleid?FROM?people?WHERE?age='17';?
SELECT?peopleid?FROM?people?WHERE?lastname='Sullivan'?AND?age='17';
from:?http://wushank.blog.51cto.com/3489095/1641308
總結(jié)
以上是生活随笔 為你收集整理的MySQL的几个概念:主键,外键,索引,唯一索引 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。