文:阿蜜果
日期:2011-10-16
版權(quán)所有,轉(zhuǎn)載請注明出處
1、 何謂數(shù)據(jù)庫主鍵
數(shù)據(jù)庫主鍵是指表中一個列或列的組合,其值能唯一地標(biāo)識表中的每一行。這樣的一列或多列稱為表的主鍵,通過它可強(qiáng)制表的實體完整性。當(dāng)創(chuàng)建或更改表時可通過定義 PRIMARY KEY 約束來創(chuàng)建主鍵。一個表只能有一個 PRIMARY KEY 約束,而且 PRIMARY KEY 約束中的列不能接受空值。由于 PRIMARY KEY 約束確保唯一數(shù)據(jù),所以經(jīng)常用來定義標(biāo)識列。
1.1 主鍵的作用
主鍵的主要作用如下:
(1)保證實體的完整性;
(2)加快數(shù)據(jù)庫的操作速度;
(3) 在表中添加新記錄時,數(shù)據(jù)庫會自動檢查新記錄的主鍵值,不允許該值與其他記錄的主鍵值重復(fù);
(4) 數(shù)據(jù)庫自動按主鍵值的順序顯示表中的記錄。如果沒有定義主鍵,則按輸入記錄的順序顯示表中的記錄。
1.2 主鍵的特點
(1)唯一性:一個表中只能有一個主鍵。如果在其他字段上建立主鍵,則原來的主鍵就會取消。
(2)非空性:主鍵的值不可重復(fù),也不可為空;
(3)必要性:在有些數(shù)據(jù)庫中,雖然主鍵不是必需的,但最好為每個表都設(shè)置一個主鍵,不管是單主鍵還是復(fù)合主鍵。它存在代表著表結(jié)構(gòu)的完整性,表的記錄必須得有唯一區(qū)分的字段,主鍵主要是用于其他表的外鍵關(guān)聯(lián),以及本記錄的修改與刪除;
(4)無意義性:在開發(fā)過程中,讀者可能會看到將一些表使用有意義的字段表示主鍵,例如“用戶登錄信息表”將“登錄名”(英文名)作為主鍵,“訂單表”中將“訂單編號”作為主鍵,如此設(shè)計主鍵一般都是沒什么問題,因為將這些主鍵基本不具有“意義更改”的可能性。但是,也有一些例外的情況,例如“訂單表”需要支持需求“訂單可以作廢,并重新生成訂單,而且訂單號要保持原訂單號一致”,那將“訂單編號”作為主鍵就滿足不了要求了。因此讀者在使用具有實際意義的字段作為主鍵時,需要考慮是否存在這種可能性。
2、 主鍵的創(chuàng)建和更改
在MySQL中,創(chuàng)建時指定某字段為主鍵的舉例如下:
create table article (
id int(4) primary key not null auto_increment,
name varchar(100) not null,
author varchar(32) not null,
publishTime datetime default NULL
);
標(biāo)示為主鍵的字段需要使用“primary key”標(biāo)識。
若要刪除某個表中之前的主鍵,并設(shè)置另外一個字段作為主鍵,參考語句如下:
ALTER TABLE 表名 DROP PRIMARY KEY, ADD PRIMARY KEY (新的主鍵字段);
主鍵可以在執(zhí)行create table操作時,在字段的后面使用“primary key”指定,也可以不位于字段后面,例如如下語句:
create table ss_schedule
(
schedulekey varchar(30) not null,
schedulename varchar(255),
updatekey varchar(30),
primary key (schedulekey)
);
3、 主鍵的選擇以及優(yōu)缺點比較
3.1 自增主鍵
這種方式是使用數(shù)據(jù)庫提供的自增數(shù)值型字段作為自增主鍵,它的優(yōu)點是:
(1)數(shù)據(jù)庫自動編號,速度快,而且是增量增長,按順序存放,對于檢索非常有利;
(2)數(shù)字型,占用空間小,易排序,在程序中傳遞也方便;
(3)如果通過非系統(tǒng)增加記錄時,可以不用指定該字段,不用擔(dān)心主鍵重復(fù)問題。
其實它的缺點也就是來自其優(yōu)點,缺點如下:
(1)因為自動增長,在手動要插入指定ID的記錄時會顯得麻煩,尤其是當(dāng)系統(tǒng)與其它系統(tǒng)集成時,需要數(shù)據(jù)導(dǎo)入時,很難保證原系統(tǒng)的ID不發(fā)生主鍵沖突(前提是老系統(tǒng)也是數(shù)字型的)。特別是在新系統(tǒng)上線時,新舊系統(tǒng)并行存在,并且是異庫異構(gòu)的數(shù)據(jù)庫的情況下,需要雙向同步時,自增主鍵將是你的噩夢;
(2)在系統(tǒng)集成或割接時,如果新舊系統(tǒng)主鍵不同是數(shù)字型就會導(dǎo)致修改主鍵數(shù)據(jù)類型,這也會導(dǎo)致其它有外鍵關(guān)聯(lián)的表的修改,后果同樣很嚴(yán)重;
(3)若系統(tǒng)也是數(shù)字型的,在導(dǎo)入時,為了區(qū)分新老數(shù)據(jù),可能想在老數(shù)據(jù)主鍵前統(tǒng)一加一個字符標(biāo)識(例如“o”,old)來表示這是老數(shù)據(jù),那么自動增長的數(shù)字型又面臨一個挑戰(zhàn)。
MySQL(auto_increment)、SQL Server(IDENTITY)、Informix、Oracle(首先創(chuàng)建自增序列,接著為自增主鍵的表創(chuàng)建插入時的觸發(fā)器,給自增主鍵ID賦值)等數(shù)據(jù)庫都支持這種自增主鍵,這種主鍵在各種系統(tǒng)中應(yīng)用廣泛,但是如果考慮到有新舊系統(tǒng)并存等問題,為了避免不必要的麻煩,使用自增主鍵要三思。
3.2 max+1主鍵
由于增主鍵存在的缺點,所以有些開發(fā)人員就采用自己生成同樣是數(shù)字型的的主鍵,但不是系統(tǒng)自動生成的。具體的方式是:在INSERT時,讀取主鍵ID的Max值后,加1,這種方法可以避免自動編號的問題,但是也存在各種缺點:
(1)效率問題:如果記錄非常大的話,那么Max()也會影響效率的;
(2)并發(fā)性問題:如果同時有兩人讀到相同的Max后,加一后插入的ID值會重復(fù)。
基于這些明顯的缺點,筆者不提倡使用此種方式。
3.3 自制+1主鍵
考慮max+1的效率后,有的開發(fā)人員采用自制加1,也就是建一個特別的表,字段為:表名、當(dāng)前序列值。這樣在往表中插入值時,先從此表中找到相應(yīng)表的最大值后加一,進(jìn)行插入,但也可能會存在并發(fā)處理,但是開發(fā)人員可以采用lock線程的方式來避免:在生成此值的時,先Lock,取到值以后,再unLock出來,這樣不會有兩人同時生成了。這比max+1的速度要快多了。
就算解決了并發(fā)的問題,但此種方式同樣存在致命的缺點:
(1)在與其他系統(tǒng)集成時,脫離了系統(tǒng)中的生成方法后,很麻煩保證自制表中的最大值與導(dǎo)入后的保持一致。
因為此種還需要創(chuàng)建新表,比較麻煩,因此筆者也不推薦此種方式。
3.4 具有實際意義的主鍵
有些表可以使用具有實際意義的主鍵,但這種表為數(shù)不多,因為要保證該字段長久的具有行記錄唯一的特點,如若有可能變成該表中的非唯一字段,那它就不適合將其變成主鍵。
筆者建議有些表可以使用具有實際意義的主鍵,例如“用戶信息表”的“用戶登錄名”字段基本都是唯一的,而且?guī)缀醪豢赡茏兂梢粋€登錄名對應(yīng)兩條記錄,因此可以使用其作為主鍵。另外,例如“一號通用戶信息表”中,“一號通號碼”肯定是唯一的,因此也可作為主鍵。
3.5 GUID主鍵
目前一個比較好的主鍵是采用GUID(Globally Unique Identifier,全球唯一標(biāo)識符),GUID的特點如下:
(1) 在空間上和時間上具有唯一性,保證同一時間不同地方產(chǎn)生的數(shù)字不同;
(2) 世界上的任何兩臺計算機(jī)都不會生成重復(fù)的GUID值;
(3) 需要GUID的時候,可以完全由算法自動生成,不需要一個權(quán)威機(jī)構(gòu)來管理;
(4) GUID的長度固定,并且相對而言較短小,非常適合于排序、標(biāo)識和存儲。
可以將GUID主鍵定義為字符型,但值由GUID生成,GUID是可以自動生成,也可以程序生成,而且鍵值不可能重復(fù),可以解決系統(tǒng)集成問題,幾個系統(tǒng)的GUID值導(dǎo)到一起時,也不會發(fā)生重復(fù),就算有“o”老數(shù)據(jù)也可以區(qū)分,而且效率很高。在SQL里也可以使用 NewID()生成。主要優(yōu)點是:
(1)同 IDENTITY 列相比,uniqueidentifier 列可以通過 NewID() 函數(shù)提前得知新增加行的ID,為應(yīng)用程序的后續(xù)處理提供很大方便;
(2)便于數(shù)據(jù)庫移植,其它數(shù)據(jù)庫中并不一定具有 IDENTITY 列,而 GUID列可以作為字符型列轉(zhuǎn)換到其它數(shù)據(jù)庫中,同時將應(yīng)用程序中產(chǎn)生的GUID值存入數(shù)據(jù)庫,它不會對原有數(shù)據(jù)帶來影響。
缺點是:
(1)GUID值較長,不容易記憶和輸入,而且這個值是隨機(jī)、無順序的。
(2)GUID的值有16個字節(jié),與其它諸如 4 字節(jié)的整數(shù)相比要相對大一些。這意味著如果在數(shù)據(jù)庫中使用 uniqueidentifier 鍵,可能會帶來兩方面的消極影響:存儲空間增大、索引時間較慢。
基于上面的分析,使用GUID的利大于弊,筆者推薦可以采用此種方式。
3.6 自制唯一字符型主鍵
為了系統(tǒng)集成等的方便,筆者建議將主鍵定義成字符型,可以使用GUID作為主鍵,也可以定義一個字符型的主鍵字段,但是它的值使用變成編程指定。該種方式的優(yōu)點是:
(1)在異庫異構(gòu)數(shù)據(jù)庫的情況下,若舊系統(tǒng)這些表的主鍵ID是自增的(數(shù)值型),而新系統(tǒng)生成的主鍵是比較長的字符串型(例如15位),那樣舊系統(tǒng)生成或之前的舊數(shù)據(jù)同步到新系統(tǒng)時,都不會沖突。
這種方式的缺點是:
(1) 需要程序能生成定長的唯一字符串,例如:當(dāng)前時間+自動機(jī)號+進(jìn)程ID+……;
(2) 由第三方系統(tǒng)生成或手動生成該主鍵時,處理比較麻煩。
3.7 總結(jié)
在上面幾種主鍵中,較為常用的是“3.1 自增主鍵”和“3.5 GUID主鍵”,當(dāng)在有些特殊的表和某些特定情況中,也可以采用“3.4 具有實際意義的主鍵”和“3.6 自制唯一的字符型主鍵”。
4、 參考文檔
(1)《主鍵設(shè)計用什么字段類型比較好》:
http://www.th7.cn/Article/bc/de/200902/20090220080511.html
(2)《主關(guān)鍵字_百度百科》:
http://baike.baidu.com/view/68068.htm
(3)《GUID_百度百科》:
http://baike.baidu.com/view/185358.htm
posted on 2011-10-16 13:10
阿蜜果 閱讀(3690)
評論(4) 編輯 收藏 所屬分類:
database