1. 序言
當前,隨著資訊量的急劇增加,對於資料的儲存和管理方式,各企業都逐漸擺脫了之前的依靠檔案系統(文字檔案或者excel)或者一些桌面型的小型資料庫系統(如access、foxbase或者dbase)的狀態,轉而通過一些大型資料庫來管理企業的資訊。這些大型資料庫系統包括oracle、ms sql server或者ibm db2。儘管目前資料庫系統也在向物件導向的資料庫系統方向發展,但是上述的傳統的關係型資料庫系統依然佔據著主要位置。
筆者從九十年代末開始以關係型資料庫系統為基礎為客戶進行管理軟體的定製化開發。主要是以powerbuilder為前台開發工具,開發出一些列的c/s結構的軟體。進入到本世紀,尤其是最近兩年,筆者又以visual studio 2003為工具,開發了一些b/s結構的應用。但是,無論是使用何種開發工具,還是開發何種結構的軟體,其後台資料庫系統依舊是關係型資料庫系統。根據客戶的應用環境,主要是在ms sql server資料庫上進行開發,當然也有基於oracle資料庫的軟體開發。
也正是因為資料量資訊量的增加,採用大型的關係型資料庫系統作為企業的資料儲存管理方式,也就要求基於資料庫開發的開發者在資料庫設計時必須遵循相應的規範。關於資料庫邏輯設計,最重要的就是資料庫表的設計,都有一套相應的理論支援,比如要滿足相應的正規化要求。一般而言,資料庫表設計滿足第二或者第三正規化即可。
在開發過程中,也盡量遵循這些相應的規則,但由於之前的經驗所限或者是在詳細設計時做的工作不夠充分,導致一些表結構不是很合理。正是這些不合理,目前出現一些問題,並且已經在部分系統中有所體現。
關於資料庫的邏輯設計,是乙個很廣泛的問題。本文主要針對筆者開發應用中的現狀,論述在ms sql server上進行表設計時,對錶的主鍵設計應注意的問題以及相應的解決辦法。
2.主鍵設計現狀和問題
2.1 現狀
關於資料庫表的主鍵設計,一般而言,是根據業務需求情況,以業務邏輯為基礎,形成主鍵。
比如,銷售時要記錄銷售情況,一般需要兩個表,乙個是銷售單的概要描述,記錄諸如銷售單號、總金額一類的情況,另外乙個表記錄每種商品的數量和金額。對於第乙個表(主表),通常我們以單據號為主鍵;對於商品銷售的明細表(從表),我們就需要將主表的單據號也放入到商品的明細表中,使其關聯起來形成主從關係。同時該單據號與商品的編碼一起,形成明細表的聯合主鍵。這只是一般情況,我們稍微將這個問題延伸一下:假如在明細中,我們每種商品又可能以不同的**方式銷售。有部分按折扣**銷售,有部分按正常**銷售。要記錄這些情況,那麼我們就需要第三個表。而這第三個表的主鍵就需要第乙個表的單據號以及第二個表的商品號再加上自身需要的資訊一起構成聯合主鍵;又或者其他情況,在第乙個主表中,本身就是以聯合方式構成聯合主鍵,那麼也需要在從表中將主表的多個字段新增進來聯合在一起形成自己的主鍵。
筆者在以前的專案中,也基本上是採取這樣的表設計思路來設計系統的表結構和主鍵。
2.2 存在的問題
在上面小節中,我們描述了當前在表的主鍵設計時的現狀。從中我們不難看出存在這樣的問題:
3. 解決方案
3.1 概述
從上面,我們已經看到現有結構存在著相當多的弊端,主要是導致程式複雜、效率降低並且不利於分頁。
為解決上述問題,本文提出:當應用系統後台資料庫表間存在主從關係時,資料庫表額外增加一非業務字段作為主鍵,該字段為數值型;或者當該表需要在應用中進行分頁查詢時,也應考慮如此設計。一般地,我們也可以幾乎為任何表增加乙個與業務邏輯無關的字段作為該錶的主鍵字段。
3.2 字段定義方式
由於該字段要作為表的主鍵,那麼其首要條件是要保證在該表中要具有唯一性。同時,結合sql server資料庫自身的特性,可以為其建立乙個自增列:
create table t_pk_demo
u_id bigint not null identity(1,1),--唯一標識記錄的id
col_other varchar(20) not null ,--其他列
constraint pk_t_pk_demo primary key nonclustered (u_id)--定義為主鍵
但是,sql server中的自增列卻存在乙個比較尷尬的事實,那就是該欄位一旦定義和使用,使用者無法直接干預該字段的值,完全由資料庫系統自身控制:
鑑於此,建議不以自增列的方式來定義,而是參考oracle資料庫系統中序列,在sql server系統中實現類似oracle資料庫系統序列功能。這個具體在下面的小節中介紹。我們只需要按照普通欄位的定義方式修改表定義為:
create table t_pk_demo
u_id bigint not null ,--唯一標識記錄的id
col_other varchar(20) not null ,--其他列
constraint pk_t_pk_demo primary key nonclustered (u_id)--定義為主鍵
3.3 序列的實現
參照oracle序列的功能,我們需要在sql server資料庫中建立乙個新錶,以管理序列值:
create table t_db_seq
seq_name varchar(50) not null ,--序列名稱
seq_owner varchar(50) not null default 』dbo』,--序列所有者(system_user)
seq_current bigint not null default 0 ,--序列當前值
seq_min bigint not null default 0 ,--序列最小值
seq_max bigint not null default 0 ,--序列最小值
seq_max bigint not null default 0 ,--序列最大值
seq_step int not null default 1 ,--序列增長步長
if_cycle int not null default 0 ,--是否迴圈(0,不迴圈;1,迴圈)
constraint t_db_seq primary key clustered (seq_name,seq_owner)--主鍵
應用系統為需要建立自增列的表建立乙個序列名稱,在表「t_db_seq」中反映為資料庫中的一行。
3.4 使用序列
第一,需要為需要建立序列的表建立乙個序列。採用方法:f_create_seq(序列名)。該函式傳入序列的名稱,在表「t_db_seq」插入一行。序列的所有者,採用系統變數system_user。
第二,獲取下乙個值。採用方法:f_get_next_seq_val(序列名)。該函式根據序列名獲取該序列的下乙個值,根據當前值與增長步長得到。同時,該函式保證在同時獲取同乙個序列時,應保證併發一致性。
第三、將返回值返回到應用使用。
此外,為保證應用的完整性,可能還需要提供一些方法的過載方法,同時提供一些其他方法:
在主從關係的表設計中,子表也使用序列字段作為唯一主鍵,將父表的序列字段作為外來鍵關聯:
create table t_pk_demo_c
u_id bigint not null ,--唯一標識記錄的id
col_other varchar(20) not null ,--其他列
p_id int not null ,--父表id
constraint pk_t_pk_demo_c primary key nonclustered (u_id)--定義為主鍵
constraint fk_t_pk_demo_c foreign key (p_id) references t_pk_demo(u_id) on delete cascade,
SQLserver資料庫 表中主鍵約束
下面就讓我們分別 這五類約束設定新增以及刪除等用法吧!1 主鍵約束 建立表時設定約束的方式有兩種 一種是在列級設定,另一種是在表級設定。在建立表時設定主鍵約束create table table name column name datatype constraint constraint name...
oralce資料庫表刪除主鍵約束
主鍵約束的建立有兩種情況 有名型和無名型,1 有名型 create table students studentid int studentname varchar 8 age int,constraint yy primary key studentid 或者 create table nbia ...
SQL Server查詢資料庫表和資料庫字段
在sql server中查詢資料庫表和字段的方式可以有三種 方法一 查詢所有表 select from sys.tables 查詢所有列 select from sys.columns 查詢所有擴充套件屬性,我們在設計資料庫表和字段時寫的中文備註等資訊會儲存在這裡 select from sys.e...