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 存在的問題
在上面小節中,我們描述了當前在表的主鍵設計時的現狀。從中我們不難看出存在這樣的問題:
資料冗餘儲存:隨著這種主從關係的延伸,資料庫中需要重複儲存的資料將變得越來越龐大。或者當主表本身就是聯合主鍵時,就必須在從表中將所有的欄位重新儲存一次。
SQL複雜度增加:當存在多個欄位的聯合主鍵時,我們需要將主表的多個欄位與子表的多個欄位關聯以擷取滿足某些條件的所有詳細情況記錄。
程式複雜度增加:可能需要傳遞多個參數。
效率降低:資料庫系統需要判斷更多的條件,SQL語句長度增加。同時,聯合主鍵自動產生聯合索引
WEB分頁困難:由於是聯合主鍵方式(對於多數的子表),那麼在WEB頁面上要進行分頁處理時,在自關聯時,難於處理。