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