一般來說關系型數據庫,絕大多數表都有數據庫主鍵。
數據庫主鍵的創建,一般有如下幾種形式:
1. 使用數據庫自增長主鍵的語法。
有些數據庫,比如 MS SQL Server, MySQL ,都有對應的語法,可以在創建數據庫表的時候,指定某個字段為自增長主鍵。Oracle , PostgreSQL 則使用 sequence , 來達到類似的作用。
以下是 MS SQL Server 示例:
create table tb(id int identity(1,1) primary key );
以下是 PostgreSQL 示例:
//serial 並不是psql的類型,只是一個宏,
create table tablename ( colname serial ); //等價於 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;
自增長數據庫主鍵,一般是 int/long 之類的整數/長整數。理論上有數據最大容量限制。
在 java/c# 代碼中,可將這種主鍵字段,轉換為 long.
2. 使用數據庫的 GUID/UUID 之類的語法。
一般是數據字段類型 + 數據庫內置函數設置默認值,來定義一個列。
以下是 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# 代碼中,可將這種主鍵字段,轉換為 string.
3. 使用字符串作為表主鍵,在java/c# 代碼中生成 uuid ,填充數值。
以下是 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, 中間有 - 分割數據,可以保留,也可以替換/去掉。
4. 使用字符型字段作為數據庫表主鍵,對應某個業務數據。比如合同號: PS21152357。
這類數據中,往往其中的某幾位,有一定的業務業務含義,比如,此處 "PS" 為合同號的標識。其它位數,為順序號。
需要編寫 在 java/c# 代碼中,來生成這種編號,並做並發防范。
總結:
方法4 , 一般稱之為“業務主鍵”。對應的, 1-3 為“邏輯主鍵”。
總體而言,應盡量避免使用“業務主鍵”。因為使用這種主鍵,有時並非系統自動生成,而是人工錄入(比如,數據源頭在 ERP,現要在另一個系統中錄入數據),人工錄入存在一定的出錯幾率,如果錄入出錯需要更改主鍵數據,則外鍵也要一並更改,往往比較麻煩。
1-3 的三種“邏輯主鍵”,我更傾向於第三種。
方法3" 使用字符串作為表主鍵,在java/c# 代碼中生成 uuid ,填充數值",不用考慮不同數據庫間的差異,可以認為任何數據庫都支持。使用起來也簡單。
如果是使用自動生成代碼工具,要看情況吧。可能有的工具,處理不了。我自己編寫的工具,處理起來沒問題。
至於 uuid 字段串,占用磁盤空間,比自增長整數/長整數占用的大的問題,其實我覺得並不是大問題。
這不會導致整個系統,磁盤空間需求,增加 1/4 或更多。一般可以忽略。
另,
數據庫主鍵的定義,在某些數據庫中,往往會自動帶上"按此字段進行順序存儲"之類的語法。比如,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 ) ) ;
這可以通過更改創建表的 SQL, 使用 PRIMARY KEY NONCLUSTERED 語法
CREATE TABLE dbo.Department ( xxx VARCHAR(10) NOT NULL PRIMARY KEY NONCLUSTERED, ... ) ;
然后再加 CLUSTERED INDEX ,來解決此問題。
CREATE CLUSTERED INDEX IX_TestTable_TestCol1 ON dbo.TestTable (TestCol1);
當然,數據庫表也可以既沒有 CLUSTERED key、 也沒有 CLUSTERED index 。
這種情況下,表的數據存儲,按 insert 的時間順序,從先到后。大多數情況下,這種數據存放方式,是可以接受的。
數據顯示時,再按照某個時間字段(交易數據, 比如銷售單的銷售時間),或者業務數據主鍵(主數據/系統配置等),進行查詢排序,查詢到排序后的數據,顯示給用戶。
===============歡迎轉載,轉載請注明出處:https://www.cnblogs.com/jacklondon/