主鍵的生成方式主要有三種:
一. 數據庫自動生成
二. GUID
三. 開發創建
嚴格講這三種產生方式有一定的交叉點,其定位方式將在下面進行講解。
第一種方式,主要將其定位在自增長的標識種子:可以設置起始數值,及增長步長。其優點在于使用時完全將并發任務交于數據庫引擎管理,你不用擔心存在多用戶使用的時候會產生兩個相同的ID的情況。其缺點也在于此,多數的數據庫不提供直接獲取標識ID的方式,對于開發人員來說產生ID的方式是透明的,開發人員幾乎無法干預此項。對于數據的遷移也不是很方便。
由于存在上面的利弊,這種自增長的ID一般多用于設計基礎表(系統運行的基礎信息,如員工表)主鍵,而極少(根本不)用于主從表主、外鍵,因為在產生主從表數據并關聯時,必須確定主表的ID,然后才能定位從表的關聯ID。
例(MsSQL):
復制代碼 代碼如下:
--創建測試表
CREATE TABLE [Identity](
Id INT IDENTITY(1,2) NOT NULL PRIMARY KEY,--種子的起始值1,步長2
Number VARCHAR(20) UNIQUE NOT NULL,
Name VARCHAR(20) NOT NULL,
Password VARCHAR(20) DEFAULT(123),
Description VARCHAR(40) NULL
)
--插入記錄
INSERT INTO [Identity](Number,Name,Description) VALUES('001','1st','Id=1,因為起始值1')
INSERT INTO [Identity](Number,Name,Description) VALUES('002','2nd','Id=3,因為起始值1,步長2')
INSERT INTO [Identity](Number,Name,Description) VALUES('003','3rd','Id=5,由于字符長度超長,報錯插入失敗,造成此Id產生后被放棄')
INSERT INTO [Identity](Number,Name,Description) VALUES('004','4th','Id=7 not 5,因為第三條記錄插入失敗')
--檢索記錄,查看結果
SELECT * FROM [Identity]
結果:
(1 行受影響)
(1 行受影響)
消息 8152,級別 16,狀態 14,第 3 行
將截斷字符串或二進制數據。
語句已終止。
(1 行受影響)
(3 行受影響)
Id Number Name Password Description
1 001 1st 123 Id=1,因為起始值1
3 002 2nd 123 Id=3,因為起始值1,步長2
7 004 4th 123 Id=7 not 5,因為第三條記錄插入失敗
第二種方式,GUID即Globally Unique Identifier,也稱為UUID(Universally Unique IDentifier),全球唯一標識符,GUID一般由32位十六進制的數值組成,其中包含網卡地址、時間及其他信息。任何兩臺電腦都不會產生相同的GUID,他的優點在唯一性,當需要數據庫整合時,能節約不少勞動力。比如總公司和分公司各自系統獨立運行,所有分公司數據定期需要提交到總部,可以避免合并數據時主鍵沖突問題,同時GUID還兼具自增長標識種子特點,無需開發人員太多的關注。但是GUID信息量大,占用空間也大,關聯檢索時,估計效率上也不是很高,對于32位的十六進制其可讀性也差,雖然主鍵有對用戶的無意義性,但是在設計或者調試交流時很不方便。
從長遠考慮,為了保證數據的可移植性,一般還是會選擇使用GUID來作為主鍵。
例(MsSQL):
復制代碼 代碼如下:
--創建測試表
CREATE TABLE GUID(
Id UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,--當然你也可以用字符串來保存
Number VARCHAR(20) UNIQUE NOT NULL,
Name VARCHAR(20) NOT NULL,
Password VARCHAR(20) DEFAULT(123)
)
--插入記錄
INSERT INTO GUID(Id,Number,Name) VALUES(NewID(),'001','1st')
INSERT INTO GUID(Id,Number,Name) VALUES(NewID(),'002','2nd')
INSERT INTO GUID(Id,Number,Name) VALUES(NewID(),'003','3rd')
--檢索記錄,查看結果
SELECT * FROM GUID
結果:
Id Number Name Password
8E194F55-B4D3-4C85-8667-33BC6CD33BBC 001 1st 123
7141F202-7D0E-4992-9164-5043EC9FC6F6 002 2nd 123
E0E365A0-8748-4656-AF24-5D0B216D2095 003 3rd 123
第三種方式開發創建,其便捷性在于可控制性,此可控制性是指其組成形式,可以是整形、也可以是字符型,你可以根據實際情況給予多樣的組成及產生形式,說到這里可能有的朋友就想起來自動產生單號,如:20120716001或者PI-201207-0001等等,沒錯,自我創建同樣適用于這些類似的應用。
說到自我創建,多數首先想到的是取Max(Id)+1,這種方式雖然省事,但是實際上對于定制(在生產單號之類的有一定意義的信息時可能會有這樣的需求,主鍵沒必要)及并發的處理并不是很好。如,當前表中最大編號為1000,當C1和C2用戶同時取這個Id處理時,得到的都是1001,導致保存失敗。常規的做法是在取值時候加鎖,但是當多用戶頻繁操作時,性能是個很大的問題,其中主要的原因之一是直接操作的業務數據表。
針對此種情況,解決方案是使用鍵值表來保存表名、當前或者下一個Id及其他信息,如果系統中多個表Id都使用這種方式,那么鍵值表中就會有多條相應的規則記錄;當然也可以讓整個數據庫所有表的Id從都按相同的規則從一個源產生,那么鍵值表中只需要一條規則記錄即可。
下面來看看這樣一個使用鍵值表例子的演變(MsSQL):
復制代碼 代碼如下: