主鍵的必要性:
有些朋友可能不提倡資料庫表必須要主鍵,但在我的思考中,覺得每個表都應該具有主鍵,不管是單主鍵還是雙主鍵,主鍵的存在就代表著表結構的完整性,表的記錄必須得有唯一區分的字段,主鍵主要是用於其他表的外來鍵關聯,本記錄的修改與刪除,當我們沒有主鍵時,這些操作會變的非常麻煩。
主鍵的無意義性:
我強調主鍵不應該具有實際的意義,這可能對於一些朋友來說不太認同,比如訂單表吧,會有「訂單編號」字段,而這個欄位呢在業務實際中本身就是應該具有唯一性,具有唯一標識記錄的功能,但我是不推薦採用訂單編號字段作為主鍵的,因為具有實際意義的字段,具有「意義更改」的可能性,比如訂單編號在剛開始的時候我們一切順利,後來客戶說「訂單可以作廢,並重新生成訂單,而且訂單號要保持原訂單號一致」,這樣原來的主鍵就面臨危險了。因此,具有唯一性的實際欄位也代表可以作為主鍵。因此,我推薦是新設乙個字段專門用為主鍵,此主鍵本身在業務邏輯上不體現,不具有實際意義。而這種主鍵在一定程式增加了複雜度,所以要視實際系統的規模大小而定,對於小專案,以後擴充套件不會很大的話,也查允許用實際唯一的字段作主鍵的。
主鍵的選擇:
我們現在在思考一下,應該採用什麼來作表的主鍵比較合理,申明一下,主鍵的設計沒有乙個定論,各人有各人的方法,哪怕同乙個,在不同的專案中,也會採用不同的主鍵設計原則。
第一:編號作主鍵
此方法就是採用實際業務中的唯一欄位的「編號」作為主鍵設計,這在小型的專案中是推薦這樣做的,因為這可以使專案比較簡單化,但在使用中卻可能帶來一些麻煩,比如要進行「編號修改」時,可能要涉及到很多相關聯的其他表,就象黎叔說的「後果很嚴重」;還有就是上面提到的「業務要求允許編號重複時」,我們再那麼先知,都無法知道業務將會修改成什麼?
第二:自動編號主鍵
這種方法也是很多朋友在使用的,就是新建乙個id欄位,自動增長,非常方便也滿足主鍵的原則。
優點是:資料庫自動編號,速度快,而且是增量增長,聚集型主鍵按順序存放,對於檢索非常有利;數字型的,占用空間小,易排序,在程式中傳遞也方便;如果通過非系統增加記錄(比如手動錄入,或是用其他工具直接在表裡插入新記錄,或老系統資料匯入)時,非常方便,不用擔心主鍵重複問題。
缺點:其實缺點也就是來自其優點,就是因為自動增長,在手動要插入指定id的記錄時會顯得麻煩,尤其是當系統與其他系統整合時,需要資料匯入時,很難保證原系統的id不發生主鍵衝突(前提是老系統也是數字型的);如果其他系統主鍵不是數字型那就麻煩更大了,會導致修改主鍵資料型別了,這也會導致其他相關表的修改,後果同樣很嚴重;就算其他系統也是數字型的,在匯入時,為了區分新老資料,可能想在老資料主鍵前統一加乙個「o」(old)來表示這是老資料,那麼自動增長的數字型又面臨乙個挑戰。
第三:max加一
由於自動編號存在那些問題,所以有些朋友就採用自己生成,同樣是數字型的,只是把自動增長去掉了,採用在insert時,讀取max值後加一,這種方法可以避免自動編號的問題,但也存在乙個效率問題,如果記錄非常大的話,那麼max()也會影響效率的;更嚴重的是併發性問題,如果同時有兩人讀到相同的max後,加一後插入的id值會重複,這已經是有經驗教訓的了。
第四:自製加一
考慮max加一的效率後,有人採用自製加一,也就是建乙個特別的表,欄位為:表名,當前序列值。這樣在往表中插入值時,先從此表中找到相應表的最大值後加一,進行插入,有人可能發現,也可能會存在併發處理,這個併發處理,我們可以採用loc**程的方式來避免,在生成此值的時,先lock,取到值以後,再unlock出來,這樣不會有兩人同時生成了。這比max加一的速度要快多了。但同樣存在乙個問題:在與其他系統整合時,脫離了系統中的生成方法後,很麻煩保證自製表中的最大值與匯入後的保持一致,而且數字型都存在上面講到的「o」老資料的匯入問題。因此在「自製加一」中可以把主鍵設為字元型的。字元型的自製加一我倒是蠻推薦的,應該字元型主鍵可以應付很多我們意想不到的情況。
第五:guid主鍵
目前乙個比較好的主鍵是採用guid,當然我是推薦主鍵還是字元型的,但值由guid生成,guid是可以自動生成,也可以程式生成,而且鍵值不可能重複,可以解決系統整合問題,幾個系統的guid值導到一起時,也不會發生重複,就算有「o」老資料也可以區分,而且效率很高,在.net裡可以直接使用system.guid.newguid()進行生成,在sql裡也可以使用 newid()生成。
優點是:
同 identity 列相比,uniqueidentifier 列可以通過 newid() 函式提前得知新增加的行 id,為應用程式的後續處理提供了很大方便。便於資料庫移植,其它資料庫中並不一定具有 identity 列,而 guid 列可以作為字元型列轉換到其它資料庫中,同時將應用程式中產生的 guid 值存入資料庫,它不會對原有資料帶來影響。 便於資料庫初始化,如果應用程式要載入一些初始資料, identity 列的處理方式就比較麻煩,而 uniqueidentifier 列則無需任何處理,直接用 t-sql 載入即可。 便於對某些物件或常量進行永久標識,如類的 classid,物件的例項標識,uddi 中的聯絡人、服務介面、tmodel標識定義等。
缺點是:
guid 值較長,不容易記憶和輸入,而且這個值是隨機、無順序的。
guid 的值有 16 個位元組,與其它那些諸如 4 位元組的整數相比要相對大一些。這意味著如果在資料庫中使用 uniqueidentifier 鍵,可能會帶來兩方面的消極影響:儲存空間增大;索引時間較慢。
我也不是推薦guid最好,其實在不同的情況,我們都可以採用上面的某一種方式,思考了一些利與弊,也方便大家在進行設計時參考。這些也只是我的一點思考而已,而且可能我知識面限制,會有一些誤論在裡面,希望大家有什麼想法歡迎討論。
資料庫主鍵設計原則
或許大家都設計過資料庫,也為表定義過主鍵,今天我想闡述的是,應該如何正確的設計乙個主鍵,在以往的一些資料中,都沒有提及到主鍵設計的原則.我為此總結了一下 1.是否要採用guid作為主鍵 用guid作主鍵有它的優勢與不足.優勢是guid具有唯一性,在任何情況下,可以產生全球唯一的值.這是guid最大的...
資料庫主鍵設計原則
資料庫主鍵設計原則 或許大家都設計過資料庫,也為表定義過主鍵,今天我想闡述的是,應該如何正確的設計乙個主鍵,在以往的一些資料中,都沒有提及到主鍵設計的原則.我為此總結了一下 1.是否要採用guid作為主鍵 用guid作主鍵有它的優勢與不足.優勢是guid具有唯一性,在任何情況下,可以產生全球唯一的值...
資料庫主鍵設計原則
資料庫主鍵設計原則 或許大家都設計過資料庫,也為表定義過主鍵,今天我想闡述的是,應該如何正確的設計乙個主鍵,在以往的一些資料中,都沒有提及到主鍵設計的原則.我為此總結了一下 1.是否要採用guid作為主鍵 用guid作主鍵有它的優勢與不足.優勢是guid具有唯一性,在任何情況下,可以產生全球唯一的值...