數據庫設計的基本方法  
  
  數據庫設計是建立數據庫及其應用系統(tǒng)的核心和基礎,它要求對于指定的應用環(huán)境,構造出較優(yōu)的數據庫模式,建立起數據庫應用系統(tǒng),并使系統(tǒng)能有效地存儲數據,滿足用戶的各種應用需求。一般按照規(guī)范化的設計方法,常將數據庫設計分為若干階段:
  系統(tǒng)規(guī)劃階段主要是確定系統(tǒng)的名稱、范圍;確定系統(tǒng)開發(fā)的目標功能和性能;確定系統(tǒng)所需的資源;估計系統(tǒng)開發(fā)的成本;確定系統(tǒng)實施計劃及進度;分析估算系統(tǒng)可能達到的效益;確定系統(tǒng)設計的原則和技術路線等。對分布式數據庫系統(tǒng),還應分析用戶環(huán)境及網絡條件,以選擇和建立系統(tǒng)的網絡結構。
  需求分析階段要在用戶調查的基礎上,通過分析,逐步明確用戶對系統(tǒng)的需求,包括數據需求和圍繞這些數據的業(yè)務處理需求。通過對組織、部門、企業(yè)等進行詳細調查,在了解現行系統(tǒng)的概況、確定新系統(tǒng)功能的過程中,收集支持系統(tǒng)目標的基礎數據及其處理方法。
  概念設計階段要產生反映企業(yè)各組織信息需求的數據庫概念結構,即概念模型。概念模型必須具備豐富的語義表達能力、易于交流和理解、易于變動、易于向各種數據模型轉換、易于從概念模型導出與DBMS有關的邏輯模型等特點。
  邏輯設計階段除了要把E-R圖的實體和聯系類型,轉換成選定的DBMS支持的數據類型,還要設計子模式并對模式進行評價,最后為了使模式適應信息的不同表示,需要優(yōu)化模式。
  物理設計階段的主要任務是對數據庫中數據在物理設備上的存放結構和存取方法進行設計。數據庫物理結構依賴于給定的計算機系統(tǒng),而且與具體選用的DBMS密切相關。物理設計常常包括某些操作約束,如響應時間與存儲要求等。
  系統(tǒng)實施階段主要分為建立實際的數據庫結構;裝入試驗數據對應用程序進行測試;裝入實際數據建立實際數據庫三個步驟。
  另外,在數據庫的設計過程中還包括一些其他設計,如數據庫的安全性、完整性、一致性和可恢復性等方面的設計,不過,這些設計總是以犧牲效率為代價的,設計人員的任務就是要在效率和盡可能多的功能之間進行合理的權衡。
數據庫編程示例  
  在本次講座中,我們以Delphi5為開發(fā)工具,標準的paradox表為后臺數據庫,來向大家介紹如何進行最簡單的數據庫編程。在本例中,我們將實現對一個數據表單的添加、修改、刪除以及對表中數據進行查詢的功能。
  本例所使用的計算機軟硬件環(huán)境為:Windows NT 4.0 Server,Borland Delphi 5,PIII550,256M內存。當然啦,一般的朋友在Win98的環(huán)境下或者Win2000的環(huán)境下都可以按照本例的步驟來編程序的。筆者的機器主要用作服務器,所以就在服務器上編啦。廢話少說,現在開始:
  在正式編寫程序之前要有許多準備工作,這當然包括Borland Delphi 5的安裝。Delphi5自身帶了對標準數據表paradox的驅動(和一些fox系列數據庫軟件的.db文件是兼容的,這些文件都可以由Delphi直接讀?。?
  程序編寫的第一步首先是數據表(即.db文件)的建立。在這一步要用到Delphi自帶的一個工具叫Database Desktop。這個工具主要用來對表格進行操作,它不僅可以操作像.db文件這樣的標準表格,還可以訪問像Oracle、SQL Server等大型數據庫的文件,功能可以說是很強大的。打開Database Desktop,選擇File-New-Table,然后選擇paradox7.
    
  在FieldName里面填寫你要建立的表單的屬性名稱,如圖所示,本例中要建立的是人員管理表,所以建立的屬性為編號、姓名、性別、工作單位、工資、備注等。除工資之外的屬性都是字符串類型,即圖中Type項所選擇的A(Alpha),而Size則是指的字符串的長度,屬性值的長度是根據屬性的具體意義來確定的,例如“性別”選擇只有“男”和“女”,一個漢字的長度,那么性別屬性的長度設置成2就可以了(一個漢字等于兩個字符的長度)。而工資屬性是數值類型的,在paradox中用Number來標記,即和前面對應的一個“N”。屬性設置完畢后,選擇Save As存盤。本例中,所建立的數據表格的存放路徑和文件名為:D:Program FilesBorlandDatabase DesktopWorkDir
yb.db(人員表)。  
  這樣就完成了第一步,這一步只是編程之前的準備工作,也是后面針對這個表單編寫數據庫應用程序的基礎。下面要進行的就是實際的程序編寫了,請打開Borland Delphi 5?! ?
  在缺省的Form1上放置這樣一些控件(控件的位置就不用俺再羅嗦了吧?):TdataBase、Ttable、TdataSourse、TdbGrid、Tlabel、TdbNavigator。按照你喜歡的界面風格來放置這些控件,下一步就是控件屬性的設置啦,這一步也是本例中最關鍵的一步,因為許多網友對使用前端開發(fā)工具對后臺數據庫進行編程比較生疏,也就是在這個地方。
  我們將Tdatabase的DataBaseName屬性設置成Mydb(這個名字可以隨便起),drivername為STANDARD(表明驅動的是paradox表),params屬性為path=D:Program FilesBorlandDatabase DesktopWorkDir(存放.db文件的路徑,前面已經提到),connected設為true(和數據表建立起連接),其他屬性使用缺省值就可以了?! ?
  然后將Table的Databasename屬性設為Mydb(即Database1的DataBaseName屬性),tablename為ryb.db(即數據表的名字)Active屬性設置為True(打開表單,便于編寫程序)?! ?
  接著將Datasourse1的dataset屬性設為為Table1(Ttable的name屬性值)。另外DBNavigator1和DbGrid1的datasourse屬性都設為datasourse1。Tlabel的caption屬性設為“數據庫編程示例”,如圖所示(可以根據個人喜好修改字體,使它變得好看一些)?! ?>這樣控件的屬性就設置完畢了,注意到dbgrid里面的“編號”、“姓名”等欄都是數據表中的屬性,在ryb.db里面定義,而不是在前端的delphi程序里面定義。點擊run按鈕之后,這個簡單的程序就運行了?! ?


        這是通過Dbnavigator上的按鈕就可以控制對表單進行數據的添加、刪除、修改了(將DbNavigator的ShowHint屬性改為True的話可以在運行時看到各個按鈕的提示)?!?BR>  
  至此,我們實現了使用Delphi這種快速開發(fā)工具編寫簡單的數據庫應用程序, 細心的讀者可能注意到了,到目前為止連一行程序都沒有寫,確實是這樣,這就是第四代程序設計語言(可視化的編程語言)給我們帶來的好處。當然啦,要編寫比較復雜的程序不寫代碼是不可能的,下面我們將在上面的基礎上實現查詢的功能,并給大家附上源程序。在Form增加如下控件:一個Tquery、一個Tbutton、4個Tlabel、2個Tedit。并將Tlabel的屬性進行下圖所示的修改(新增加的控件都在黑色方框中):                     
  將Query1的DataBaseName屬性也設置成MyDb(和Table一樣),SQL屬性中寫入Select* from ryb,RequestLive設為True(這樣可以對Query里面的數據進行修改),然后將Active屬性設為True。最后將DataSourse1的DataSet屬性改為query1(此時Table1控件可以從Form上去掉了)?! ?
  雙擊Button1,在程序編輯器里面寫入如下代碼:  
Query1.close;  
   Query1.Sql.clear;  
   Query1.SQL.Add(Select * from ryb);  
   Query1.sql.add(where 姓名 like :xm and 工資 > :gz);  
   Query1.ParamByName(xm).asstring:=%+Edit1.text+%;  
If (Edit2.text<>’’)then  
   Query1.ParamByName(gz).value:=strtofloat(Edit2.text);  
   Query1.prepare;  
   Query1.open;   >
  
   這樣就完成了查詢代碼的編寫,具體各條語句所引用的函數的含義大家可以參考Delphi的幫助文檔,在此就不作贅述了。另外在編寫查詢程序時,涉及到一些關于數據庫查詢語言SQL的知識,在后面的文章中我們將有比較詳細的介紹。   >此時再執(zhí)行這個程序,就編程的具有查詢功能的數據庫程序。在Edit1和Edit2中輸入相應的查詢條件,然后點擊Button1(確定),程序就執(zhí)行相應的查詢操作,查詢到的結果將在DBGrid1中顯示?! ?
  到此為止,我們就實現了使用Borland Delphi5操縱paradox數據表的程序示例,當然,這個程序是非常簡單的,它實現的只是數據庫操作的最基本功能。而且這個程序只是在單擊環(huán)境下運行的,在設計的時候,我們還不需要考慮一些例如并發(fā)性的問題?,F在比較成熟的是在客戶機/服務器結構下和瀏覽器/服務器下對數據庫進行操作,而且隨著網絡功能的加入,許多新的問題也帶入進來,在后面我們將舉這方面的例子,請大家靜候佳音吧!


一個好的數據庫產品不等于就有一個好的應用系統(tǒng),如果不能設計一個合理的數據庫模型,不僅會增加客戶端和服務器段程序的編程和維護的難度,而且將會影響系統(tǒng)實際運行的性能。一般來講,在一個MIS系統(tǒng)分析、設計、測試和試運行階段,因為數據量較小,設計人員和測試人員往往只注意到功能的實現,而很難注意到性能的薄弱之處,等到系統(tǒng)投入實際運行一段時間后,才發(fā)現系統(tǒng)的性能在降低,這時再來考慮提高系統(tǒng)性能則要花費更多的人力物力,而整個系統(tǒng)也不可避免的形成了一個打補丁工程。筆者依據多年來設計和使用數據庫的經驗,提出以下一些設計準則,供同仁們參考。


命名的規(guī)范  
  
  不同的數據庫產品對對象的命名有不同的要求,因此,數據庫中的各種對象的命名、后臺程序的代碼編寫應采用大小寫敏感的形式,各種對象命名長度不要超過30個字符,這樣便于應用系統(tǒng)適應不同的數據庫。


游標(Cursor)的慎用   
  
  游標提供了對特定集合中逐行掃描的手段,一般使用游標逐行遍歷數據,根據取出的數據不同條件進行不同的操作。尤其對多表和大表定義的游標(大的數據集合)循環(huán)很容易使程序進入一個漫長的等特甚至死機,筆者在某市《住房公積金管理系統(tǒng)》進行日終帳戶滾積數計息處理時,對一個10萬個帳戶的游標處理導致程序進入了一個無限期的等特(后經測算需48個小時才能完成)(硬件環(huán)境:Alpha/4000 128Mram ,Sco Unix,Sybase 11.0),后根據不同的條件改成用不同的UPDATE語句得以在二十分鐘之內完成。


示例如下:   
  
Declare Mycursor cursor for select count_no from COUNT


Open Mycursor
Fetch Mycursor into @vcount_no
While (@@sqlstatus=0)
  Begin
       If @vcount_no=’’ 條件1
          操作1
       If @vcount_no=’’ 條件2
          操作2
       。。。
       Fetch Mycursor into @vcount_no
  End
。。。
。。。
改為
Update COUNT set 操作1 for 條件1
Update COUNT set 操作2 for 條件2
。。。
。。。
  在有些場合,有時也非得使用游標,此時也可考慮將符合條件的數據行轉入臨時表中,再對臨時表定義游標進行操作,可時性能得到明顯提高。筆者在某地市〈電信收費系統(tǒng)〉數據庫后臺程序設計中,對一個表(3萬行中符合條件的30多行數據)進行游標操作(硬件環(huán)境:PC服務器,PII266 64Mram ,NT4.0 Ms Sqlserver 6.5)。 示例如下:
Create #tmp  /* 定義臨時表 */
( 字段1
字段2
。。。
)
Insert into #tmp select * from TOTAL where 條件 /* TOTAL中3萬行 符合條件只有幾十行 */
Declare Mycursor cursor for select * from #tmp
/*對臨時表定義游標*/
。。。


索引(Index)的使用原則
  創(chuàng)建索引一般有以下兩個目的:維護被索引列的唯一性和提供快速訪問表中數據的策略。大型數據庫有兩種索引即簇索引和非簇索引,一個沒有簇索引的表是按堆結構存儲數據,所有的數據均添加在表的尾部,而建立了簇索引的表,其數據在物理上會按照簇索引鍵的順序存儲,一個表只允許有一個簇索引,因此,根據B樹結構,可以理解添加任何一種索引均能提高按索引列查詢的速度,但會降低插入、更新、刪除操作的性能,尤其是當填充因子(Fill Factor)較大時。所以對索引較多的表進行頻繁的插入、更新、刪除操作,建表和索引時因設置較小的填充因子,以便在各數據頁中留下較多的自由空間,減少頁分割及重新組織的工作。


數據的一致性和完整性   
  為了保證數據庫的一致性和完整性,設計人員往往會設計過多的表間關聯(Relation),盡可能的降低數據的冗余。表間關聯是一種強制性措施,建立后,對父表(Parent Table)和子表(Child Table)的插入、更新、刪除操作均要占用系統(tǒng)的開銷,另外,最好不要用Identify 屬性字段作為主鍵與子表關聯。如果數據冗余低,數據的完整性容易得到保證,但增加了表間連接查詢的操作,為了提高系統(tǒng)的響應時間,合理的數據冗余也是必要的。使用規(guī)則(Rule)和約束(Check)來防止系統(tǒng)操作人員誤輸入造成數據的錯誤是設計人員的另一種常用手段,但是,不必要的規(guī)則和約束也會占用系統(tǒng)的不必要開銷,需要注意的是,約束對數據的有效性驗證要比規(guī)則快。所有這些,設計人員在設計階段應根據系統(tǒng)操作的類型、頻度加以均衡考慮。


事務的陷阱  
  事務是在一次性完成的一組操作。雖然這些操作是單個的操作,SQL Server能夠保證這組操作要么全部都完成,要么一點都不做。正是大型數據庫的這一特性,使得數據的完整性得到了極大的保證。


  眾所周知,SQL Server為每個獨立的SQL語句都提供了隱含的事務控制,使得每個DML的數據操作得以完整提交或回滾,但是SQL Server還提供了顯式事務控制語句
—- BEGIN TRANSACTION 開始一個事務
—- COMMIT TRANSACTION 提交一個事務
—- ROLLBACK TRANSACTION 回滾一個事務
—- 事務可以嵌套,可以通過全局變量@@trancount檢索到連接的事務處理嵌套層次。
  需要加以特別注意并且極容易使編程人員犯錯誤的是,每個顯示或隱含的事物開始都使得該變量加1,每個事務的提交使該變量減1,每個事務的回滾都會使得該變量置0,而只有當該變量為0時的事務提交(最后一個提交語句時),這時才把物理數據寫入磁盤。


數據庫性能調整   
  在計算機硬件配置和網絡設計確定的情況下,影響到應用系統(tǒng)性能的因素不外乎為數據庫性能和客戶端程序設計。而大多數數據庫設計員采用兩步法進行數據庫設計:首先進行邏輯設計,而后進行物理設計。數據庫邏輯設計去除了所有冗余數據,提高了數據吞吐速度,保證了數據的完整性,清楚地表達數據元素之間的關系。而對于多表之間的關聯查詢(尤其是大數據表)時,其性能將會降低,同時也提高了客 戶端程序的編程難度,因此,物理設計需折衷考慮,根據業(yè)務規(guī)則,確定對關聯表的數據量大小、數據項的訪問頻度,對此類數據表頻繁的關聯查詢應適當提高數據冗余設計。


數據類型的選擇   
  數據類型的合理選擇對于數據庫的性能和操作具有很大的影響,有關這方面的書籍也有不少的闡述,這里主要介紹幾點經驗。
Identify字段不要作為表的主鍵與其它表關聯,這將會影響到該表的數據遷移。
Text 和Image字段屬指針型數據,主要用來存放二進制大型對象(BLOB)。這類數據的操作相比其它數據類型較慢,因此要避開使用。
日期型字段的優(yōu)點是有眾多的日期函數支持,因此,在日期的大小比較、加減操作上非常簡單。但是,在按照日期作為條件的查詢操作也要用函數,相比其它數據類型速度上就慢許多,因為用函數作為查詢的條件時,服務器無法用先進的性能策略來優(yōu)化查詢而只能進行表掃描遍歷每行。
  例如:要從DATA_TAB1中(其中有一個名為DATE的日期字段)查詢1998年的所有記錄。

分享到

多易

相關推薦