主鍵
在關(guān)系數(shù)據(jù)庫中,一張表中的每一行數(shù)據(jù)被稱為一條記錄。一條記錄就是由多個(gè)字段組成的。例如,students表的兩行記錄:
id class_id name gender score
1 1 小明 M 90
2 1 小紅 F 95
每一條記錄都包含若干定義好的字段。同一個(gè)表的所有記錄都有相同的字段定義。
對(duì)于關(guān)系表,有個(gè)很重要的約束,就是任意兩條記錄不能重復(fù)。不能重復(fù)不是指兩條記錄不完全相同,而是指能夠通過某個(gè)字段唯一區(qū)分出不同的記錄,這個(gè)字段被稱為主鍵。
例如,假設(shè)我們把name字段作為主鍵,那么通過名字小明或小紅就能唯一確定一條記錄。但是,這么設(shè)定,就沒法存儲(chǔ)同名的同學(xué)了,因?yàn)椴迦胂嗤麈I的兩條記錄是不被允許的。
對(duì)主鍵的要求,最關(guān)鍵的一點(diǎn)是:記錄一旦插入到表中,主鍵最好不要再修改,因?yàn)橹麈I是用來唯一定位記錄的,修改了主鍵,會(huì)造成一系列的影響。
由于主鍵的作用十分重要,如何選取主鍵會(huì)對(duì)業(yè)務(wù)開發(fā)產(chǎn)生重要影響。如果我們以學(xué)生的身份證號(hào)作為主鍵,似乎能唯一定位記錄。然而,身份證號(hào)也是一種業(yè)務(wù)場(chǎng)景,如果身份證號(hào)升位了,或者需要變更,作為主鍵,不得不修改的時(shí)候,就會(huì)對(duì)業(yè)務(wù)產(chǎn)生嚴(yán)重影響。
所以,選取主鍵的一個(gè)基本原則是:不使用任何業(yè)務(wù)相關(guān)的字段作為主鍵。
因此,身份證號(hào)、手機(jī)號(hào)、郵箱地址這些看上去可以唯一的字段,均不可用作主鍵。
作為主鍵最好是完全業(yè)務(wù)無關(guān)的字段,我們一般把這個(gè)字段命名為id。常見的可作為id字段的類型有:
自增整數(shù)類型:數(shù)據(jù)庫會(huì)在插入數(shù)據(jù)時(shí)自動(dòng)為每一條記錄分配一個(gè)自增整數(shù),這樣我們就完全不用擔(dān)心主鍵重復(fù),也不用自己預(yù)先生成主鍵;
全局唯一GUID類型:使用一種全局唯一的字符串作為主鍵,類似8f55d96b-8acc-4636-8cb8-76bf8abc2f57。GUID算法通過網(wǎng)卡MAC地址、時(shí)間戳和隨機(jī)數(shù)保證任意計(jì)算機(jī)在任意時(shí)間生成的字符串都是不同的,大部分編程語言都內(nèi)置了GUID算法,可以自己預(yù)算出主鍵。
對(duì)于大部分應(yīng)用來說,通常自增類型的主鍵就能滿足需求。我們?cè)趕tudents表中定義的主鍵也是BIGINT NOT NULL AUTO_INCREMENT類型。
如果使用INT自增類型,那么當(dāng)一張表的記錄數(shù)超過2147483647(約21億)時(shí),會(huì)達(dá)到上限而出錯(cuò)。使用BIGINT自增類型則可以最多約922億億條記錄。
聯(lián)合主鍵
關(guān)系數(shù)據(jù)庫實(shí)際上還允許通過多個(gè)字段唯一標(biāo)識(shí)記錄,即兩個(gè)或更多的字段都設(shè)置為主鍵,這種主鍵被稱為聯(lián)合主鍵。
對(duì)于聯(lián)合主鍵,允許一列有重復(fù),只要不是所有主鍵列都重復(fù)即可:
id_num id_type other columns...
1 A ...
2 A ...
2 B ...
如果我們把上述表的id_num和id_type這兩列作為聯(lián)合主鍵,那么上面的3條記錄都是允許的,因?yàn)闆]有兩列主鍵組合起來是相同的。
沒有必要的情況下,我們盡量不使用聯(lián)合主鍵,因?yàn)樗o關(guān)系表帶來了復(fù)雜度的上升。
小結(jié)
主鍵是關(guān)系表中記錄的唯一標(biāo)識(shí)。主鍵的選取非常重要:主鍵不要帶有業(yè)務(wù)含義,而應(yīng)該使用BIGINT自增或者GUID類型。主鍵也不應(yīng)該允許NULL。
可以使用多個(gè)列作為聯(lián)合主鍵,但聯(lián)合主鍵并不常用。