時間:2015-06-28 00:00:00 來源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評論(0)
關(guān)于數(shù)據(jù)庫的邏輯設(shè)計,是一個很廣泛的問題。本文主要針對開發(fā)應(yīng)用中遇到在MS SQL Server上進行表設(shè)計時,對表的主鍵設(shè)計應(yīng)注意的問題以及相應(yīng)的解決辦法。
主鍵設(shè)計現(xiàn)狀和問題
關(guān)于數(shù)據(jù)庫表的主鍵設(shè)計,一般而言,是根據(jù)業(yè)務(wù)需求情況,以業(yè)務(wù)邏輯為基礎(chǔ),形成主鍵。
比如,銷售時要記錄銷售情況,一般需要兩個表,一個是銷售單的概要描述,記錄諸如銷售單號、總金額一類的情況,另外一個表記錄每種商品的數(shù)量和金額。對于第一個表(主表),通常我們以單據(jù)號為主鍵;對于商品銷售的明細表(從表),我們就需要將主表的單據(jù)號也放入到商品的明細表中,使其關(guān)聯(lián)起來形成主從關(guān)系。同時該單據(jù)號與商品的編碼一起,形成明細表的聯(lián)合主鍵。這只是一般情況,我們稍微將這個問題延伸一下:假如在明細中,我們每種商品又可能以不同的價格方式銷售。有部分按折扣價格銷售,有部分按正常價格銷售。要記錄這些情況,那么我們就需要第三個表。而這第三個表的主鍵就需要第一個表的單據(jù)號以及第二個表的商品號再加上自身需要的信息一起構(gòu)成聯(lián)合主鍵;又或者其他情況,在第一個主表中,本身就是以聯(lián)合方式構(gòu)成聯(lián)合主鍵,那么也需要在從表中將主表的多個字段添加進來聯(lián)合在一起形成自己的主鍵。
數(shù)據(jù)冗余存儲:隨著這種主從關(guān)系的延伸,數(shù)據(jù)庫中需要重復(fù)存儲的數(shù)據(jù)將變得越來越龐大?;蛘弋斨鞅肀旧砭褪锹?lián)合主鍵時,就必須在從表中將所有的字段重新存儲一次。
SQL復(fù)雜度增加:當存在多個字段的聯(lián)合主鍵時,我們需要將主表的多個字段與子表的多個字段關(guān)聯(lián)以獲取滿足某些條件的所有詳細情況記錄。
程序復(fù)雜度增加:可能需要傳遞多個參數(shù)。
效率降低:數(shù)據(jù)庫系統(tǒng)需要判斷更多的條件,SQL語句長度增加。同時,聯(lián)合主鍵自動生成聯(lián)合索引
WEB分頁困難:由于是聯(lián)合主鍵方式(對于多數(shù)的子表),那么在WEB頁面上要進行分頁處理時,在自關(guān)聯(lián)時,難于處理。
解決方案
從上面,我們已經(jīng)看到現(xiàn)有結(jié)構(gòu)存在著相當多的弊端,主要是導(dǎo)致程序復(fù)雜、效率降低并且不利于分頁。
為解決上述問題,本文提出:當應(yīng)用系統(tǒng)后臺數(shù)據(jù)庫表間存在主從關(guān)系時,數(shù)據(jù)庫表額外增加一非業(yè)務(wù)字段作為主鍵,該字段為數(shù)值型;或者當該表需要在應(yīng)用中進行分頁查詢時,也應(yīng)考慮如此設(shè)計。一般地,我們也可以幾乎為任何表增加一個與業(yè)務(wù)邏輯無關(guān)的字段作為該表的主鍵字段。
由于該字段要作為表的主鍵,那么其首要條件是要保證在該表中要具有唯一性。同時,結(jié)合SQL Server數(shù)據(jù)庫自身的特性,可以為其建立一個自增列:
以下為引用的內(nèi)容: create TABLE T_PK_DEMO |
但是,SQL Server中的自增列卻存在一個比較尷尬的事實,那就是該字段一旦定義和使用,用戶無法直接干預(yù)該字段的值,完全由數(shù)據(jù)庫系統(tǒng)自身控制:
完全數(shù)據(jù)庫系統(tǒng)控制,用戶無法修改值
在數(shù)據(jù)庫的發(fā)布和訂閱時,使用自增列會比較麻煩
恢復(fù)部分數(shù)據(jù)時,使用自增列會比較麻煩
該列的值必須在插入數(shù)據(jù)后才能獲取
鑒于此,建議不以自增列的方式來定義,而是參考Oracle數(shù)據(jù)庫系統(tǒng)中序列,在SQL Server系統(tǒng)中實現(xiàn)類似Oracle數(shù)據(jù)庫系統(tǒng)序列功能。這個具體在下面的小節(jié)中介紹。我們只需要按照普通字段的定義方式修改表定義為:
以下為引用的內(nèi)容: create TABLE T_PK_DEMO |
參照Oracle序列的功能,我們需要在SQL Server數(shù)據(jù)庫中創(chuàng)建一個新表,以管理序列值:
以下為引用的內(nèi)容: create TABLE T_DB_SEQ |
應(yīng)用系統(tǒng)為需要創(chuàng)建自增列的表創(chuàng)建一個序列名稱,在表"T_DB_SEQ"中反映為數(shù)據(jù)庫中的一行。
第一,需要為需要建立序列的表創(chuàng)建一個序列。采用方法:F_create_SEQ(序列名)。該函數(shù)傳入序列的名稱,在表"T_DB_SEQ"插入一行。序列的所有者,采用系統(tǒng)變量SYSTEM_USER。
第二,獲取下一個值。采用方法:F_GET_NEXT_SEQ_VAL(序列名)。該函數(shù)根據(jù)序列名獲取該序列的下一個值,根據(jù)當前值與增長步長得到。同時,該函數(shù)保證在同時獲取同一個序列時,應(yīng)保證并發(fā)一致性。
第三、將返回值返回到應(yīng)用使用。
此外,為保證應(yīng)用的完整性,可能還需要提供一些方法的重載方法,同時提供一些其他方法:
獲取序列當前值:F_GET_SEQ_CUR_VAL(序列名)
設(shè)置序列值:F_SET_SEQ_VAL(序列名)
刪除序列:F_DEL_SEQ(序列名)
判斷序列是否存在:F_SEQ_exists(序列名)
在主從關(guān)系的表設(shè)計中,子表也使用序列字段作為唯一主鍵,將父表的序列字段作為外鍵關(guān)聯(lián):
以下為引用的內(nèi)容: create TABLE T_PK_DEMO_C |
使用序列的問題及解決辦法
由于系統(tǒng)使用一個額外增加一個字段作為主鍵,因此沒有為業(yè)務(wù)邏輯建立主鍵約束。比如在企業(yè)用戶信息表中,要求企業(yè)中用戶登錄名必須唯一。一般在創(chuàng)建表時,以登錄名作為主鍵,這個時候在數(shù)據(jù)庫層自然的創(chuàng)建另一個主鍵唯一性約束。而現(xiàn)在沒有使用登錄名作為主鍵,那么就沒有這個約束。解決辦法:
一是在數(shù)據(jù)庫層解決。可以為該表創(chuàng)建一個唯一(UNIQUE)約束或者唯一索引。如:
alter TABLE T_PK_DEMO ADD CONSTRAINT C_T_PK_DEMO UNIQUE NONCLUSTERED(COL_OTHER)-唯一約束
create UNIQUE INDEX IX_T_PK_DEMO
關(guān)鍵詞標簽:SQL Server
相關(guān)閱讀
熱門文章
淺談JSP JDBC來連接SQL Server 2005的方法
SqlServer2005對現(xiàn)有數(shù)據(jù)進行分區(qū)具體步驟
sql server系統(tǒng)表損壞的解決方法
MS-SQL2005服務(wù)器登錄名、角色、數(shù)據(jù)庫用戶、角色、架構(gòu)的關(guān)系
人氣排行 配置和注冊O(shè)DBC數(shù)據(jù)源-odbc數(shù)據(jù)源配置教程 如何遠程備份(還原)SQL2000數(shù)據(jù)庫 SQL2000數(shù)據(jù)庫遠程導(dǎo)入(導(dǎo)出)數(shù)據(jù) SQL2000和SQL2005數(shù)據(jù)庫服務(wù)端口查看或修改 修改Sql Server唯一約束教程 SQL Server 2005降級到2000的正確操作步驟 sql server系統(tǒng)表損壞的解決方法 淺談JSP JDBC來連接SQL Server 2005的方法