關(guān)系型數(shù)據(jù)庫(kù)的幾種常用主鍵
一般來(lái)說(shuō)關(guān)系型數(shù)據(jù)庫(kù),絕大多數(shù)表都有數(shù)據(jù)庫(kù)主鍵。
數(shù)據(jù)庫(kù)主鍵的創(chuàng)建,一般有如下幾種形式:
1. 使用數(shù)據(jù)庫(kù)自增長(zhǎng)主鍵的語(yǔ)法。
有些數(shù)據(jù)庫(kù),比如 MS SQL Server, MySQL ,都有對(duì)應(yīng)的語(yǔ)法,可以在創(chuàng)建數(shù)據(jù)庫(kù)表的時(shí)候,指定某個(gè)字段為自增長(zhǎng)主鍵。Oracle , PostgreSQL 則使用 sequence , 來(lái)達(dá)到類(lèi)似的作用。
以下是 MS SQL Server 示例:
create table tb(id int identity(1,1) primary key );
以下是 PostgreSQL 示例:
//serial 并不是psql的類(lèi)型,只是一個(gè)宏,
create table tablename ( colname serial ); //等價(jià)于 CREATE SEQUENCE tablename_colname_seq; CREATE TABLE tablename ( colname integer NOT NULL DEFAULT nextval('tablename_colname_seq') ); ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
自增長(zhǎng)數(shù)據(jù)庫(kù)主鍵,一般是 int/long 之類(lèi)的整數(shù)/長(zhǎng)整數(shù)。理論上有數(shù)據(jù)最大容量限制。
在 java/c# 代碼中,可將這種主鍵字段,轉(zhuǎn)換為 long.
2. 使用數(shù)據(jù)庫(kù)的 GUID/UUID 之類(lèi)的語(yǔ)法。
一般是數(shù)據(jù)字段類(lèi)型 + 數(shù)據(jù)庫(kù)內(nèi)置函數(shù)設(shè)置默認(rèn)值,來(lái)定義一個(gè)列。
以下是 MS SQL Server 示例:
CREATE TABLE dbo.Globally_Unique_Data ( GUID UNIQUEIDENTIFIER CONSTRAINT Guid_Default DEFAULT NEWSEQUENTIALID() ROWGUIDCOL, Employee_Name VARCHAR(60) CONSTRAINT Guid_PK PRIMARY KEY (GUID) );
在 java/c# 代碼中,可將這種主鍵字段,轉(zhuǎn)換為 string.
3. 使用字符串作為表主鍵,在java/c# 代碼中生成 uuid ,填充數(shù)值。
以下是 MS SQL Server 示例:
CREATE TABLE [dbo].[tt_process_request]( [process_request_uuid] [varchar](40) NOT NULL, ... [created_time] [datetime] NULL, [created_by] [varchar](50) NULL, [updated_time] [datetime] NULL, [updated_by] [varchar](50) NULL, [updated_cnt] [bigint] NULL, CONSTRAINT [PK_tt_process_request] PRIMARY KEY CLUSTERED ( [process_request_uuid] ASC );
C# 生成 uuid 的代碼示例:
string fileUuid = System.Guid.NewGuid().ToString();
Java 生成 uuid 的代碼示例如下:
public String createUuid() { return UUID.randomUUID().toString().replaceAll("-", ""); }
代碼生成的 uuid, 中間有 - 分割數(shù)據(jù),可以保留,也可以替換/去掉。
4. 使用字符型字段作為數(shù)據(jù)庫(kù)表主鍵,對(duì)應(yīng)某個(gè)業(yè)務(wù)數(shù)據(jù)。比如合同號(hào): PS21152357。
這類(lèi)數(shù)據(jù)中,往往其中的某幾位,有一定的業(yè)務(wù)業(yè)務(wù)含義,比如,此處 "PS" 為合同號(hào)的標(biāo)識(shí)。其它位數(shù),為順序號(hào)。
需要編寫(xiě) 在 java/c# 代碼中,來(lái)生成這種編號(hào),并做并發(fā)防范。
總結(jié):
方法4 , 一般稱之為“業(yè)務(wù)主鍵”。對(duì)應(yīng)的, 1-3 為“邏輯主鍵”。
總體而言,應(yīng)盡量避免使用“業(yè)務(wù)主鍵”。因?yàn)槭褂眠@種主鍵,有時(shí)并非系統(tǒng)自動(dòng)生成,而是人工錄入(比如,數(shù)據(jù)源頭在 ERP,現(xiàn)要在另一個(gè)系統(tǒng)中錄入數(shù)據(jù)),人工錄入存在一定的出錯(cuò)幾率,如果錄入出錯(cuò)需要更改主鍵數(shù)據(jù),則外鍵也要一并更改,往往比較麻煩。
1-3 的三種“邏輯主鍵”,我更傾向于第三種。
方法3" 使用字符串作為表主鍵,在java/c# 代碼中生成 uuid ,填充數(shù)值",不用考慮不同數(shù)據(jù)庫(kù)間的差異,可以認(rèn)為任何數(shù)據(jù)庫(kù)都支持。使用起來(lái)也簡(jiǎn)單。
如果是使用自動(dòng)生成代碼工具,要看情況吧。可能有的工具,處理不了。我自己編寫(xiě)的工具,處理起來(lái)沒(méi)問(wèn)題。
至于 uuid 字段串,占用磁盤(pán)空間,比自增長(zhǎng)整數(shù)/長(zhǎng)整數(shù)占用的大的問(wèn)題,其實(shí)我覺(jué)得并不是大問(wèn)題。
這不會(huì)導(dǎo)致整個(gè)系統(tǒng),磁盤(pán)空間需求,增加 1/4 或更多。一般可以忽略。
另,
數(shù)據(jù)庫(kù)主鍵的定義,在某些數(shù)據(jù)庫(kù)中,往往會(huì)自動(dòng)帶上"按此字段進(jìn)行順序存儲(chǔ)"之類(lèi)的語(yǔ)法。比如,SQL Server ,以下是示例:
CREATE TABLE [dbo].[tt_process_request]( [process_request_uuid] [varchar](40) NOT NULL, ..., CONSTRAINT [PK_tt_process_request] PRIMARY KEY CLUSTERED ( [process_request_uuid] ASC ) ) ;
這可以通過(guò)更改創(chuàng)建表的 SQL, 使用 PRIMARY KEY NONCLUSTERED 語(yǔ)法
CREATE TABLE dbo.Department ( xxx VARCHAR(10) NOT NULL PRIMARY KEY NONCLUSTERED, ... ) ;
然后再加 CLUSTERED INDEX ,來(lái)解決此問(wèn)題。
CREATE CLUSTERED INDEX IX_TestTable_TestCol1 ON dbo.TestTable (TestCol1);
當(dāng)然,數(shù)據(jù)庫(kù)表也可以既沒(méi)有 CLUSTERED key、 也沒(méi)有 CLUSTERED index 。
這種情況下,表的數(shù)據(jù)存儲(chǔ),按 insert 的時(shí)間順序,從先到后。大多數(shù)情況下,這種數(shù)據(jù)存放方式,是可以接受的。
數(shù)據(jù)顯示時(shí),再按照某個(gè)時(shí)間字段(交易數(shù)據(jù), 比如銷(xiāo)售單的銷(xiāo)售時(shí)間),或者業(yè)務(wù)數(shù)據(jù)主鍵(主數(shù)據(jù)/系統(tǒng)配置等),進(jìn)行查詢排序,查詢到排序后的數(shù)據(jù),顯示給用戶。
===============歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處:http://www.rzrgm.cn/jacklondon/

浙公網(wǎng)安備 33010602011771號(hào)