第一篇:圖書倉庫管理系統論文(共)
前 言
隨著社會經濟的迅速發展和科學技術的全面進步,計算機事業的飛速發展,以計算機與通信技術為基礎的信息系統正處于蓬勃發展的時期.隨著經濟文化水平的顯著提高,人們對生活質量及工作環境的要求也越來越高.書籍做為人類的精神食糧,在現代社會中越來越受到重視,大量的書籍出現在市場上,人們有了各種各樣不同的選擇.與此同時,為了管理大量的圖書,圖書倉庫也大量的出現,倉庫的管理問題也就提上了日程.隨著圖書的大量增加,其管理難度也越來越大,如何優化倉庫的日常管理也就成為了一個大眾化的課題.在計算機飛速發展的今天,將計算機這一信息處理利器應用于倉庫的日常管理已是勢必所然,而且這也將為倉庫管理帶來前所未有的改變,它可以帶來意想不到的效益,同時也會為企業的飛速發展提供無限潛力.采用計算機管理信息系統已成為倉庫管理科學化和現代化的重要標志,它給企業管理來了明顯的經濟效益和社會效益.主要體現在:
極大提高了倉庫工作人員的工作效率,大大減少了以往入出存流程繁瑣,雜亂,周期長的弊端.基于倉庫管理的全面自動化,可以減少入庫管理,出庫管理及庫存管理中的漏洞,可以節約不少管理開支,增加企業收入.倉庫的管理的操作自動化和信息的電子化,全面提高了倉庫的管理水平.隨著我國改革開放的不斷深入,經濟飛速的發展,企業要想生存,發展,要想在激烈的市場競爭中立于不敗之地,沒有現代化的管理是萬萬不行的,倉庫管理的全面自動化,信息化則是其中極其重要的部分.為了加快倉庫管理自動化的步伐,提高倉庫的管理業務處理效率,建立倉庫管理系統已變得十分心要.入庫,庫存,出庫還是現在企業圖書倉庫管理的常規基本模式,雖然,最近又出現了很多新的管理模式,如:基于零庫存思想的沃爾瑪特管理方式,但這些新的思想在中國大部分企業的管理中還是難以實現的.所以如何設計好倉庫管理系統,盡可能地減少倉庫管理的重復性和低效性就成為當前最為重要的問題.圖書倉庫管理的核心是入庫,庫存和出庫之間的聯系,如何處理好三者之間的關系是系統最為關鍵的部分.另外,員工信息和供應商信息管理也是倉庫管理中一個必不可少的部分,它提供著與入庫和出庫相關的一些信息,使得整個系統更加完整,更加實用.通過對倉庫管理日常工作的詳細調查,搜集了大量的資料,從系統結構的組織,功能的實現,技術的要求以及可行性等多方面進行考慮,認為本課題是一個適應現今圖書倉庫管理需求的計算機信息管理系統,具有一定的實際開發價值和使用價值.
第二篇:Delphi圖書倉庫管理系統論文
Delphi圖書倉庫管理系統論文Delphi圖書倉庫管理系統論文
前 言
隨著社會經濟的迅速發展和科學技術的全面進步,計算機事業的飛速發展,以計算機與通信技術為基礎的信息系統正處于蓬勃發展的時期.隨著經濟文化水平的顯著提高,人們對生活質量及工作環境的要求也越來越高.書籍做為人類的精神食糧,在現代社會中越來越受到重視,大量的書籍出現在市場上,人們有了各種各樣不同的選擇.與此同時,為了管理大量的圖書,圖書倉庫也大量的出現,倉庫的管理問題也就提上了日程.隨著圖書的大量增加,其管理難度也越來越大,如何優化倉庫的日常管理也就成為了一個大眾化的課題.在計算機飛速發展的今天,將計算機這一信息處理利器應用于倉庫的日常管理已是勢必所然,而且這也將為倉庫管理帶來前所未有的改變,它可以帶來意想不到的效益,同時也會為企業的飛速發展提供無限潛力.采用計算機管理信息系統已成為倉庫管理科學化和現代化的重要標志,它給企業管理來了明顯的經濟效益和社會效益.主要體現在:
極大提高了倉庫工作人員的工作效率,大大減少了以往入出存流程繁瑣,雜亂,周期長的弊端.基于倉庫管理的全面自動化,可以減少入庫管理,出庫管理及庫存管理中的漏洞,可以節約不少管理開支,增加企業收入.倉庫的管理的操作自動化和信息的電子化,全面提高了倉庫的管理水平.隨著我國改革開放的不斷深入,經濟飛速的發展,企業要想生存,發展,要想在激烈的市場競爭中立于不敗之地,沒有現代化的管理是萬萬不行的,倉庫管理的全面自動化,信息化則是其中極其重要的部分.為了加快倉庫管理自動化的步伐,提高倉庫的管理業務處理效率,建立倉庫管理系統已變得十分心要.入庫,庫存,出庫還是現在企業圖書倉庫管理的常規基本模式,雖然,最近又出現了很多新的管理模式,如:基于零庫存思想的沃爾瑪特管理方式,但這些新的思想在中國大部分企業的管理中還是難以實現的.所以如何設計好倉庫管理系統,盡可能地減少倉庫管理的重復性和低效性就成為當前最為重要的問題.圖書倉庫管理的核心是入庫,庫存和出庫之間的聯系,如何處理好三者之間的關系是系統最為關鍵的部分.另外,員工信息和供應商信息管理也是倉庫管理中一個必不可少的部分,它提供著與入庫和出庫相關的一些信息,使得整個系統更加完整,更加實用.通過對倉庫管理日常工作的詳細調查,搜集了大量的資料,從系統結構的組織,功能的實現,技術的要求以及可行性等多方面進行考慮,認為本課題是一個適應現今圖書倉庫管理需求的計算機信息管理系統,具有一定的實際開發價值和使用價值.內 容 簡 介
本系統主要完成對圖書倉庫的庫存管理,包括圖書入庫,出庫,庫存,員工信息,供應商信息以及密碼管理等六個方面.系統可以完成對各類信息的瀏覽,查詢,添加,刪除,修改,報表等功能.系統的核心是入庫,庫存和出庫三者之間的聯系,每一個表的修改都將聯動的影響其它的表,當完成入庫或出庫操作時系統會自動地完成庫存的修改.查詢功能也是系統的核心之一,在系統中即有單條件查詢和多條件查詢,也有精確查詢和模糊查詢,系統不僅有靜態的條件查詢,也有動態生成的條件查詢,其目的都是為了方便用戶使用.系統有完整的用戶添加,刪除和密碼修改功能,并具備報表打印功能.系統采用MICROSOFT OFFICE中的ACCESS 2000來設計數據庫,并使用當前優秀的開發工具—DELPHI 6.0 ,它有著最為靈活的數據庫結構,對數據庫應用有著良好的支持.論文主要介紹了本課題的開發背景,所要完成的功能和開發的過程.重點的說明了系統設計的重點,設計思想,難點技術和解決方案.具體安排如下:
第一章進行系統的需求分析.第二章介紹系統的概要設計.第三章介紹了系統詳細設計.第四章介紹了程序設計環境及選用的語言工具.第五章根據前四章的設計結果利用ACCESS 2000和DELPHI 6.0進行了具體的窗體和應用程序設計.總結部分介紹了設計體會和編程體會,并指出了系統設計中的不足和改進的方向.關鍵字:圖書倉庫管理,數據庫,DELPHI,SQL,ACCESS.
第三篇:圖書倉庫管理系統(doc 61)
管理資源吧(www.tmdps.cn),海量企業管理資料免費下載!
圖書倉庫管理系統
摘 要
本系統主要完成對圖書倉庫的庫存管理,包括圖書入庫、出庫、庫存,員工信息,供應商信息以及密碼管理等六個方面。系統可以完成對各類信息的瀏覽、查詢、添加、刪除、修改、報表等功能。
系統的核心是入庫、庫存和出庫三者之間的聯系,每一個表的修改都將聯動的影響其它的表,當完成入庫或出庫操作時系統會自動地完成庫存的修改。查詢功能也是系統的核心之一,在系統中即有單條件查詢和多條件查詢,也有精確查詢和模糊查詢,系統不僅有靜態的條件查詢,也有動態生成的條件查詢,其目的都是為了方便用戶使用。系統有完整的用戶添加、刪除和密碼修改功能,并具備報表打印功能。
系統采用Microsoft Office中的Access 2000來設計數據庫,并使用當前優秀的開發工具—Delphi 6.0,它有著最為靈活的數據庫結構,對數據庫應用有著良好的支持。
論文主要介紹了本課題的開發背景,所要完成的功能和開發的過程。重點的說明了系統設計的重點、設計思想、難點技術和解決方案。
關鍵字:數據庫,SQL語言,Delph 6,數據庫組件,倉庫管理
目 錄
更多免費下載,敬請登陸:www.tmdps.cn 第一章 引言 ?????????????????????????????1 1.1 課題來源 ??????????????????????????1 1.2 開發工具的選擇 ???????????????????????2 1.3 所做的主要工作 ???????????????????????3 第二章 數據庫概論 ??????????????????????????4
2.1 數據庫的發展 ????????????????????????4 2.1.1 數據庫的發展 ??????????????????????4 2.1.2 數據庫階段的特點 ????????????????????5 2.1.3 數據庫技術 ???????????????????????6 2.2 數據庫理論基礎 ???????????????????????7 2.2.1 數據庫模型 ???????????????????????7 2.2.2 數據庫體系結構 ????????????????????10
2.2.3 數據的獨立性 ?????????????????????11 2.2.4 范式 ?????????????????????????11 2.3 SQL語言基礎 ???????????????????????13 2.3.1 SQL簡介 ???????????????????????13 2.3.2 SQL查詢 ???????????????????????13 2.3.3 SQL數據更新 ?????????????????????14 第三章數據庫開發工具 ???????????????????????16 3.1 Delphi 6.0 簡介 ???????????????????????16
3.2 Delphi 6.0 控件 ???????????????????????17 3.2.1 ADO數據訪問組件 ???????????????????17 3.2.2 數據控制類DataControl ?????????????????18 3.2.3 數據訪問類DataAccess ?????????????????18 3.2.4 SQL語言在Delphi中的應用 ???????????????19 3.3 Access 簡介 ????????????????????????21 第四章 系統總體設計 ????????????????????????23
4.1 系統需求分析 ???????????????????????23 4.2 系統概要設計 ???????????????????????25 4.2.1 系統結構設計 ?????????????????????25 4.2.2 數據庫設計 ??????????????????????27
4.2.2.1 ER圖設計 ????????????????????27 4.2.2.2 數據庫表格設計??????????????????29 4.3系統詳細設計????????????????????????34 第五章 系統應用程序設計 ??????????????????????37
5.1 系統窗體模塊組成??????????????????????37 5.2 數據模塊窗體設置??????????????????????38 5.3 主窗體功能模塊的實現????????????????????39 5.4 入庫、出庫窗體模塊的實現??????????????????43 5.5 查詢功能的實現???????????????????????51 5.6 系統登陸窗體模塊的實現???????????????????52 5.7 用戶管理功能的實現?????????????????????54 5.7.1 用戶管理主窗體 ????????????????????54 5.7.2 密碼修改窗體模塊的實現 ????????????????54 5.7.3 用戶注冊窗體模塊的實現 ????????????????55 5.7.4 用戶注銷窗體模塊的實現 ????????????????57 結束語 ???????????????????????????????59 致謝 ????????????????????????????????60 參考文獻 ??????????????????????????????61 第一章 引 言 §1.1 課題來源
隨著社會經濟的迅速發展和科學技術的全面進步,計算機事業的飛速發展,以計算機與通信技術為基礎的信息系統正處于蓬勃發展的時期。隨著經濟文化水平的顯著提高,人們對生活質量及工作環境的要求也越來越高。書籍做為人類的精神食糧,在現代社會中越來越受到重視,大量的書籍出現在市場上,人們有了各種各樣不同的選擇。與此同時,為了管理大量的圖書,圖書倉庫也大量的出現,倉庫的管理問題也就提上了日程。隨著圖書的大量增加,其管理難度也越來越大,如何優化倉庫的日常管理也就成為了一個大眾化的課題。
在計算機飛速發展的今天,將計算機這一信息處理利器應用于倉庫的日常管理已是勢必所然,而且這也將為倉庫管理帶來前所未有的改變,它可以帶來意想不到的效益,同時也會為企業的飛速發展提供無限潛力。采用計算機管理信息系統已成為倉庫管理科學化和現代化的重要標志,它給企業管理來了明顯的經濟效益和社會效益。主要體現在:
極大提高了倉庫工作人員的工作效率,大大減少了以往入出存流程繁瑣,雜亂,周期長的弊端。
基于倉庫管理的全面自動化,可以減少入庫管理、出庫管理及庫存管理中的漏洞,可以節約不少管理開支,增加企業收入。
倉庫的管理的操作自動化和信息的電子化,全面提高了倉庫的管理水平。隨著我國改革開放的不斷深入,經濟飛速的發展,企業要想生存、發展,要想在激烈的市場競爭中立于不敗之地,沒有現代化的管理是萬萬不行的,倉庫管理的全面自動化、信息化則是其中極其重要的部分。為了加快倉庫管理自動化的步伐,提高倉庫的管理業務處理效率,建立倉庫管理系統已變得十分心要。入庫、庫存、出庫還是現在企業圖書倉庫管理的常規基本模式,雖然,最近又出現了很多新的管理模式,如:基于零庫存思想的沃爾瑪特管理方式,但這些新的思想在中國大部分企業的管理中還是難以實現的。所以如何設計好倉庫管理系統,盡可能地減少倉庫管理的重復性和低效性就成為當前最為重要的問題。圖書倉庫管理的核心是入庫、庫存和出庫之間的聯系,如何處理好三者之間的關系是系統最為關鍵的部分。另外,員工信息和供應商信息管理也是倉庫管理中一個必不可少的部分,它提供著與入庫和出庫相關的地一些信息,使得整個系統更加完整,更加實用。
通過對倉庫管理日常工作的詳細調查,搜集了大量的資料,從系統結構的組織,功能的實現,技術的要求以及可行性等多方面進行考慮,認為本課題是一個適應現今圖書倉庫管理需求的計算機信息管理系統,具有一定的實際開發價值和使用價值。
§1.2 開發工具的選擇 自Java誕生以來,隨著Internet技術的普及和應用需求的變化,以第四代語言為主的應用開發產品發生了較大的變化,它們不僅已成為人們開發應用的開發工具,而且很多產品已發展成為一種強有力的應用開發環境。這些新型的開發工具通常以一種集成軟件包的形式提供給開發人員,被稱為Studio(工作室)或Suite(程序組)。例如,微軟的Visual Studio 6.0,Borland公司的Delphi 6.0等數據庫輔助開發工具。
現在,市場上可以選購的應用開發產品很多,流行的也有數十種。目前在我國市場上最為流行、使用最多、最為先進的可用作企業級開發工具的產品有: Microsoft公司的Visual Basic 6.0版 Microsoft公司的Visual C++6.0版 Borland公司的Delphi 6.0版
在目前市場上這些眾多的程序開發工具中,有些強調程語言的彈性與執行效率;有些則偏重于可視化程序開發工具所帶來的便利性與效率的得高,各有各的優點和特色,也滿足了不同用戶的需求。然而,語言的彈性和工具的便利性是密不可分的,只有便利的工具,卻沒有彈性的語言作支持,許多特殊化的處理動作必需要耗費數倍的工夫來處理,使得原來所標榜的效率提高的優點失去了作用;相反,如果只強調程語言的彈性,卻沒有便利的工具作配合,會使一些即使非常簡單的界面處理動作,也會嚴重地浪費程序設計師的寶貴時間。
而Delphi是一個非常理想選擇。Delphi 6 是操作系統中快速應用開發環境的最新版本。它也是當前Windows平臺上第一個全面支持最新Web服務的快速開發工具。無論是企業級用戶,還是個人開發者,都能夠利用Delphi 6 輕松、快捷地構建新一代電子商務應用。Delphi 6 是惟一支持所有新出現的工業標準的RAD環境,包括XML(擴展標記語言)/XSL(可擴展樣式語言),SOAP(簡單對象存取協議)和WSDL(Web服務器描述語言)等。
Delphi 6 是可視化的快速應用程序開發語言,它提供了可視化的集成開發環境,這一環境為應用程序設計人員提供了一系列靈活而先進的工具,可以廣泛地用于種類應用程序設計。在Delphi 6 的集成開發環境中,用戶可以設計程序代碼、運行程序、進行程序錯誤的調試等,可視化的開發方法降低了應用程序開發的難度。Delphi的基礎編程語言是具有面向對象特性的Pascal語言,即Object Pascal。Object Pascal具有代碼穩定、可讀性好、編譯速度快等優點,并將面向對象的概念移植到了Pascal語言中,使這種基礎語言有了新的發展空間。使用Delphi 6.0,我們幾乎可以作任何事情,還可以撰寫種各種類型的應用程序,動態鏈接庫(DLL)、CON、或CORBA對象,CGI/ISAPI程序,Microsoft Back Office應用程序。程序的規模小到簡單的個人數據庫應用,大到復雜的企業的多層次分布式系統,都可以使用Delphi進行開發,其友好的集成開發界面,可視化的雙向開發模式,良好的數據庫應用支持高效的程序開發和程序運行,備受廣大程序開發人員的好評。尤其是Delphi對數據庫應用的強大支持,大大提高了數據庫應用軟件開發的效率,縮短了開發周期,深受廣大數據庫應用程序設計人員的喜愛。Delphi為數據庫應用開發人員提供了豐富的數據庫開發組件,使數據庫應用開發功能更強大,控制更靈活,編譯后的程序運行速度更快。§1.3 本文所做工作
引言部分介紹了本系統的課題來源以及對數據庫開發工具的選擇。
第二章介紹了數據庫的發展,關系數據庫,數據庫體系結構,并系統介紹了SQL語言,為設計和理解應用程序做了鋪墊。
第三章系統介紹了Delphi 6.0及其部分控件,SQL語言在Delphi 6.0中的應用,以及Access等。
第四章是本文的主體,按照軟件工程的要求,從需求分析開始,經過概要設計最后到詳細設計,完成對整個系統的設計。
第五章根據第四章的設計結果利用Access 2000和Delphi 6.0進行了具體的窗體和應用程序設計。
總結部分介紹了設計體會和編程體會,并指出了系統設計中的不足和改進的方向 第二章 數據庫概論 §2.1 數據庫的發展
數據庫處理在信息系統的研究中一直是非常重要的主題,然而,近年來,隨著World Wide Web(www.tmdps.cn公司的TOTAL等
(3)關系模型。關系模型的主要是用二維表格結構表達實體集,用外鍵表示實體間聯系。關系模型是由若干個關系模式組成的集合。關系模式相當于前面提到的記錄類型,它的實例稱為關系,每個關系實際上是一張二維表格。
關系模型和層次、網狀模型的最大判別是用關鍵碼而不是用指針導航數據,表格簡單用戶易懂,編程時并不涉及存儲結構,訪問技術等細節。關系模型是數學化模型。SQL語言是關系數據庫的標準化語言,已得到了廣泛的應用。20世紀70年代對關系數據庫的研究主要集中在理論和實驗系統的開發方面。80年代初才形成產品,但很快得到廣泛的應用和普及,并最終取代了層次、網狀數據庫產品。現在市場上典型的關系DBMS產品有DB2、ORACLE、SYBASE、INFORMIX和微機型產品Foxpro、Access等。
關系模型和網狀、層次模型的最大區別是:關系模型用表格數據而不是通過指針鏈來表示和實現實體間聯系。關系模型的數據結構簡單、易懂。只需用簡單的查詢語句就可對數據庫進行操作。
關系模型是數學化的模型,可把表格看成一個集合,因此集合論、數理邏輯等知識可引入到關系模型中來。關系模型已是一個成熟的有前途的模型,已得到廣泛應用。
(4)面向對象模型。目前,關系數據庫的使用已相當普遍,但是,現實世界中仍然存在著許多含有復雜數據結構的應用領域,例如,CAD數據、圖形數據等,而關系模型在這方面的處理能力就顯得力不從心。因此,人們需要更高級的數據庫技術來表達這類信息。面向對象的概念最早出現在程序設計語言中,隨后迅速滲透到計算機領域的每一個分支。面向對象數據庫是面向對象概念與數據庫技術相結合的產物。
面向對象模型能完整地描述現實世界的數據結構,具有豐富的表達能力,但模型相對較復雜,涉及的知識面也廣,因此面向對象數據庫尚未達到關系數據庫那樣的普及程度。
2.2.2 數據庫體系結構
數據庫的體系結構分三級:內部級(internal),概念級(conceptual)和外部級(external)。這個三級結構有時也稱為“三級模式結構”,或“數據抽象的三個級別”,最早是在1971年通過的DBTG報告中提出,后來收入在1975年的美國ANSI/SPARC報告中。雖然現在DBMS的產品多種多樣,在不同的操作系統支持下工作,但是大多數系統在總的體系結構上都具有三級模式的結構特征。從某個角度看到的數據特性稱為“數據視圖”(data view)。外部級最接近用戶,是單個用戶所能看到的數據特性。單個用戶使用的數據視圖的描述稱為“外模式”。
概念級涉及到所有用戶的數據定義,是全局的數據視圖。全局數據視圖的描述稱為“概念模式”。
內部級最接近于物理存儲設備,涉及到實際數據存儲的結構。物理存儲數據視圖的描述稱為“內模式”。
數據庫的三級模式結構是數據的三個抽象級別。它把數據的具體組織留給DBMS去做,用戶只要抽象地處理數據,而不必關心數據在計算機中的表示和存儲,這樣就減輕了用戶使用系統的負擔。
三級結構之間往往差別很大,為了實現這三個抽象級別的聯系和轉換,DBMS在三級結構之間提供兩個層次的映象(mappings):外模式/模式映象,模式/內模式映象。此處模式是概念模式的簡稱。2.2.3 數據的獨立性
由于數據庫系統采用三級模式結構,因此系統具有數據獨立性的特點。在數據庫技術中,數據獨立性是指應用程序和數據之間相互獨立,不受影響。數據獨立性分成物理數據獨立性和邏輯數據獨立性兩級。(1)物理數據獨立性
如果數據庫的內模式要進行修改,即數據庫的存儲設備和存儲方法有所變化,那么模式/內模式映象也要進行相當的修改,使概念模式盡可能保持不變。也就是對內模式的修改盡量不影響概念模式,當然,對于外模式和應用程序的影響更小,這樣,我們稱數據庫達到了物理數據獨立性。(2)邏輯數據獨立性
如果數據庫的概念模式要進行修改,譬如增加記錄類型或增加數據項,那么外模式/模式映象也要進行相應的修改,使外模式盡可能保持不變。也就是對概念模式的修改盡量不影響外模式和應用程序,這樣,我們稱數據庫達到了邏輯數據獨立性。現有關系系統產品均提供了較高的物理獨立性,而對邏輯獨立性的支持尚有欠缺,例如,對外模式的數據更新受到限制等。2.2.4 范式
建立起一個良好的數據指標體系,是建立數據結構和數據庫的最重要的一環。一個良好的數據指標體系是建立DB的必要條件,但不是充分條件。我們完全可以認為所建指標體系中的一個指標類就是關系數據庫中的一個基本表,而這個指標類下面的一個個具體指標就是這個基本表中的一個字段。但如果直接按照這種方式建庫顯然還不能算最佳。對于指標體系中數據的結構在建庫前還必須進行規范化的重新組織。
在數據的規范化表達中,一般將一組相互關聯的數據稱為一個關系(relation),而在這個關系下的每個數據指標項則被稱為數據元素(data element),這種關系落實到具體數據庫上就是基本表,而數據元素就是基本表中的一個字段(field)。規范化表達還規定在每一個基本表中必須定義一個數據元素為關鍵字(key),它可以唯一地標識出該表中其它相關的數據元素。在規范化理論中表是二維的,它有如下四個性質:
在表中的任意一列上,數據項應屬于同一個屬性(如圖中每一列都存放著不同合同記錄的同一屬性數據)。
表中所有行都是不相同的,不允許有重復組項出現(如圖中每一行都是一個不同的合同記錄)。
在表中,行的順序無關緊要(如圖中每行存的都是合同記錄,至于先放哪一個合同都沒關系)。
在表中,列的順序無關緊要,但不能重復(如圖中合同號和合同名誰先誰后都沒關系,但二者不可重復或同名)。
在對表的形式進行了規范化定義后,數據結構還有五種規范化定義,定名為規范化模式,稱為范式。在這五種范式中,一般只用前三種,對于常用系統就足夠了。而且這五種范式是“向上兼容”的,即滿足第五范式的數據結構自動滿足一、二、三、四范式,滿足第四范式的數據結構自動滿足第一、二、三范式,??,依此類推。
第一范式(first normal form,簡稱1st NF)就是指在同一表中沒有重復項出現,如果有則應將重復項去掉。這個去掉重復項的過程就稱之為規范化處理。在本文所討論的開發方法里,1st NF實際上是沒有什么意義的。因為我們按規范化建立的指標體系和表的過程都自動保證了所有表都滿足1st NF。
第二范式(second normal form,簡稱 2nd NF)是指每個表必須有一個(而且僅一個)數據元素為主關鍵字(primary key),其它數據元素與主關鍵字一一對應。例如,在圖l9.7中如果我們將合同號定義為主關鍵字(其它數據元素中的記錄數據都有可能重名,故不能作為主關鍵字),故只要知道了一個合同記錄的合同號,就可以唯一地在同一行中找到該合同的任何一項具體信息。通常我們稱這種關系為函數依賴(functional depEndence)關系。即表中其它數據元素都依賴于主關鍵字,或稱該數據元素唯一地被主關鍵字所標識。
第三范式(third normal form,簡稱 3rd NF)就是指表中的所有數據元素不但要能夠唯一地被主關鍵字所標識,而且它們之間還必須相互獨立,不存在其它的函數關系。也就是說對于一個滿足了 2nd NF的數據結構來說,表中有可能存在某些數據元素依賴于其它非關鍵宇數據元素的現象,必須加以消除。
為防止數據庫出現更新異常、插入異常、刪除異常、數據冗余太大等現象,關系型數據庫要盡量按關系規范化要求進行數據庫設計。
§2.3 SQL語言基礎 2.3.1 SQL簡介
用戶對數據庫的使用,是通過數據庫管理系統提供的語言來實現的。不同的數據庫管理系統提供不同的數據庫語言。關系數據庫管理系統幾乎都提供關系數據庫標準語言——SQL。SQL 的全稱是Structured Query Language,即結構化查詢語言。SQL語句可以從關系數據庫中獲得數據,也可以建立數據庫、增加數據、修改數據。1986年ANSI采用SQL語言作為關系數據庫系統的標準語言,后被國際化標準組織(ISO)采納為國際標準。SQL語言使用方便、功能豐富、簡潔易學,是操作數據庫的工業標準語言,得到廣泛地應用。例如關系數據庫產品DB2、ORACLE等都實現了SQL語言。同時,其它數據庫產品廠家也紛紛推出各自的支持SQL的軟件或者與SQL的接口軟件。這樣SQL語言很快被整個計算機界認可。
SQL語言是一種非過程化語言,它一次處理一個記錄集合,對數據提供自動導航。SQL語言允許用戶在高層的數據結構上工作,而不對單個記錄進行操作。SQL語言不要求用戶指定數據的存取方法,而是使用查詢優化器,由系統決定對指定數據存取的最快速手段。當設計者在關系表上定義了索引時,系統會自動利用索引進行快速檢索,用戶不需知道表上是否有索引或者有什么類型的索引等細節。SQL語言可以完成許多功能,例如: ● 查詢數據
● 在數據庫表格中插入、修改和刪除記錄 ● 建立、修改和刪除數據對象 ● 控制對數據和數據對象的存取 ● 確保數據庫的一致性和完整性等 2.3.2 SQL查詢
數據查詢是關系運算理論在SQL語言中的主要體現,SELECT 語句是SQL查詢的基本語句,當我們在對一個數據庫進各種各樣的操作時,使用的最多的就是數據查詢,在以SQL為基礎的關系數據庫中,使用的最多的就是SELECT查詢語句。SELECT語句的完整句法如下: SELECT 目標表的列名或列表達式序列 FROM 基本表和(或)視圖序列 [WHERE 行條件表達式] [GROUP BY 列名序列] [HAVING 組條件表達式] [ORDER BY列名 [ASC│DEAC]?] 我在SELECT語句中還使用了大量的保留字和通配符以進行各種各樣的條件查詢。在系統中有大量的查詢按鈕,其使用了大量的查詢語句,而且這些查詢語句大部分使用的是模糊查詢,所以大量的使用了模式匹配符LIKE(判斷值是否與指定的字符通配格式相符)。在包含LIKE的查詢語句中可以使用兩個通配符:%(百分號):與零個或多個字符組成的字符串匹配;_(下劃線):與單個字符匹配。系統中的條件判斷往往包含多個條件,這時就需要使用邏輯運算符NOT、AND、OR(用于多條件的邏輯連接),謂詞ALL以及保留字DISTINCT等等。做為SELECT語句還有很多的使用方法,這里就不再敘述。2.3.3 SQL數據更新
使用數據庫的目的是為了有效地管理數據,而數據的插入、刪除和修改則是必不可少的一個功能。在本系統中就大量地使用了數據插入、刪除和修改這三種操作,現做一個簡單地介紹。●數據插入
往數據庫的基本表中插入數據使用的是INSERT語句,其方式有兩種:一種是元組值的插入,另一種是查詢結果的插入。在本系統中使用的是前一種方式,其句法如下:
INSERT INTO 基本表名(列表名)VALUES(元組值)●數據刪除
往數據庫的基本表中刪除數據使用的是DELETE語句,其句法如下: DELETE FROM 基本表名 [WHERE 條件表達式] 在些作一點說明,刪除語句實際上是“SELECT * FROM 基本表名 [WHERE 條件表達式]”和DELETE操作的結合,每找到一個元組,就把它刪除。此外,DELETE語句只能從一個基本表中刪除元組,WHERE子句中條件可以嵌套,也可以是來自幾個基本表的復合條件。●數據修改
當需要修改基本表中元組的某些列值時,可以用UPDATE語句實現,其句法如下: UPDATE基本表名
SET列名=值表達式[,列名=值表達式?] [WHERE條件表達式] 在Delphi中使用SQL語句是很方便的,一般來說,都是通過TQuery組件來使用SQL語言的。有一點要進行說明,雖然通過TQuery組件來使用SQL語言很方便,但考慮到自己對不同組件的理解程度、個人習慣以及其它各個方面,在本系統中我采用的是ADO組件來對數據庫進行操作。最簡單的方法比如在TADOQuery組件的SQL屬性中就可以鍵入SQL語句,至于詳細的使用方法在后面進行介紹。第三章 數據庫開發工具 §3.1 Delphi 6.0 簡介
Delphi類可以粗略地分成兩部分:一部分是組件類,這些組件類通常以某種方式出現在組件面板上,當用戶從組件面板上點取一個類的圖標后,在程序中就自動生成了該類的對象(非可視組件除外);另一部分是功能類,這此功能類的對象通常出現在程序代碼中,起著不可代替的作用,但是這些功能類在組件面板上是找不到的。在Delphi中,每一個類的祖先都是Tobject類,整個類的層次結構就像一棵倒掛的樹,在最頂層的樹根即為Tobject類。這樣,按照面向對象編程的基本思想,就使得用戶可用Tobject類這個類型代替任何其它類的數據類型。實際上在Delphi的類庫中,Tobject類派生出了為數相當眾多的子類,它們形成了一個龐大的體系,通常情況下,如果不自行開發組件,就不必了解整個類的體系結構,只用到類層次樹的葉結點就足夠了。
凡是做過程序開發的人都知道從來沒有單純的數據應用程序,也就是說,數據庫應用程序必須和用戶界面(可以是圖形界面,也可以是命令接口)元素相結合,只講界面或只講數據庫本身都構不成數據庫應用程序,因而用Delphi 6.0開發數據庫應用程序就隱含著界面開發。Delphi6中的VCL組件可用圖3-1來說明。組件在Delphi程序的開發中是最顯眼的角色。大家知道,在編寫程序時一般都開始于在組件面板上選擇組件并定義組件間的相互作用。但也有一些組件不在組件面板上,例如Tform和Tapplication(典型的非可視組件)。組件是Tcomponents派生出來的子類,可以流的形式存放在DFM文件中,具有事件和Publish屬性。窗口組件類是窗口化的可視化組件類,在Delphi的類庫中占有最大的份額。在實際編程中,窗口組件類的對象都有句柄,可以接受輸入焦點和包含其它組件。圖形組件與窗口組件并列,是另一大類組件。圖形組件不是基于窗口的,因而不能有窗口句柄,不能接受輸入焦點和包含其它組件。從圖8-43中可以看出,圖形組件的基類是TgraphicControl,在實際編程中,它們必須寄生于它們的宿主——窗口組件類的對象,由它們的擁有者負責其顯示,而且它們還能觸發一些和鼠標活動相關的事件。圖形控件最典型的例子是Tlabel和TspeedButton。由此可以看出圖形組件的功能很弱,有讀者會問圖形組件的用處何在呢?其實使用圖形組件的最大好處在于節省資源,正是因為它們的功能較弱,所以使用的系統資源就要少。在一個應用程序中,如果能在不影響其功能的前提下合理大量地使用圖形組件,將會大減少程序對系統資源的消耗。
非可視組件是與可視組件相并列的另一類組件,非可視組件在程序運行中是不可見的(除各種對話框組件之外,事實上有人認為對話框組件不能歸入非可視組件,應該是另一種介于可視與非可視之間的組件)。§3.2 Delphi 6.0 控件
用Delphi6開發數據庫應用,重點是和各種數據庫組件打交道,當然也要使用其它的一些組件,現在就我在系統設計中所使用的重要組件給與簡單介紹。3.2.1 ADO數據訪問組件
ADO數據對象(Active Data Objects)實際是一種提供訪問各種數據類型的鏈接機制。ADO設計為一種極簡單的格式,通過ODBC的方法同數據庫接口中,可以使用任何一種ODBC數據源,即不止適合于SQL Server、Oracle、Access等數據庫應用程序,也適合于Excel表格、文本文件、圖形文件和無格式的數據文件。ADO是基于OLE-DB之上的技術,因此ADO通過其內部的屬性和方法提供統一的數據訪問接口方法。ADO使您的客戶端應用程序能夠通過OLE DB提供訪問和操作在數據庫服務器中的數據。ADO支持用于建立C/S和Web的應用程序的主要功能。其主要優點是易于使用、高速度、低內存支出和占用磁盤空間較少。ADO同時具有遠程數據服務(RDS)功能,通過RDS可以在一次往返過程中實現將數據從服務器移動到客戶端應用程序和Web頁、在客戶端對數據進行處然后將更新結果返回服務器的操作。
Delphi 6.0繼續對Microsoft的ADO訪問能力的支持。這種能力是通過一組新組件實現的,這些組件是在企業版的ADO組件頁中,在組件面版的ADO頁上可以找到這些組件。利用在前面章節提到的TdataSet抽象類,ADO組件可以不通過BDE而直接實現ADO連接。這意味著只需要很少的代碼就可以實現該連接并且性能得到提高。
利用ADO數據訪問組件,可以只使用ADO結構與數據庫取得聯系并對其中的數據進行操作,而在這些過程中完全不需要使用BDE。大多數的ADO連接和數據集組件都是與基于BDE的連接和數據集組件相類似的。TADOConnection組件與基于BDE的應用程序中的Tdatabase組件類似。TADOTable與Ttable,TADOQuery與Tquery,以及TADOStoreProc和TstoredProc之間都具有這種類似的對應關系。使用這些ADO組件的方式與我們常使用的數據訪問組件(基于BDE)都有許多相同之處。TTADODataSet沒有直接的BDE對應組件,但它提供了許多與Ttable和Tquery相同的功能。同樣,TADOCommand也沒有相對應的BDE組件,它是在Delphi/ADO環境中完成特定功能的組件。Delphi 6.0通過ADO數據集訪問組件,可以不借助BDE數據引擎而是通過微軟的OLEDB來訪問更為廣泛的數據庫中的數據。ADO數據集訪問組件與常用的數據訪問組件是并列的關系。在系統中我主要使用的是ADOTablet和ADOQuery兩個組件。3.2.2 數據控制類DataControl 數據控制類負責數據庫數據的顯示,并把用戶對數據的修改傳回。這里的絕大多數組件,如DBText, DBEdit, DBMemo, DBImage, DBListBox, DBComboBox, DBCheckBox, DBRadioGroup, DBLookupListBox, DBLookupCombox, DBCtrGrid的功能和對應的非數據感知組件相同,如TEdit框,TRadioGroups單選按鈕組等,只不過在顯示數據庫數據時要用而已。
在系統中主要使用數據網格控件DBGrid和數據庫導航器控件DBNavigator。3.2.3 數據訪問類DataAccess 數據庫應用系統中數據訪問是一個首要問題,包括單用戶和 C/S系統,都必須聯系一些數據庫和數據表文件。Delphi 6 提供了專門用于數據訪問的基類控件。主要包括數據源控件DataSource、客戶數據集控件ClientDataSet、數據集提供器控件DataSetProvider等等。
Tdatabase:當一個基于BDE的數據庫應用程序需要一個永久數據庫連接時,需要定制向一個數據庫服務器的連接時,需要事務控制和特殊的數據庫別名時就得用到Tdatabase對象。特別是當連接到一個遠程的SQL數據庫服務器時,如果要利用BDE進行數據庫事務處理,那么,TDatabase對象的威力就體現出來了。在一個應用程序中為每一個數據庫連接顯示的聲明Tdatabase對象要根據需要而定,不是必需的。對一個數據庫連接,如果沒有顯示的聲明并實例化TDatabase對象,系統就會產生一個帶有默認屬性的TDatabase對象。
TdataSource對象用于在DataSet對象(包括Tquery,TstoredProc,Ttable等)和數據感知組件之間提供一個連接的紐帶,以便在窗體上顯示數據庫中的數據,在數據庫中導航定位與編輯數據集中的數據。如果一個DataSet對象中的數據想在數據感知組件中顯示和修改,它就必須和TdataSource對象相聯系。同樣,一個數據感知組件如果想和數據源相聯系以便顯示和操縱數據,就必須以TDataSource對象為中介。
用Delphi6作數據庫應用開發概括來說如下:先利用數據存取組件和實際的數據庫建立連接,并用Tsession對象和Tdatabase對象管理這些連接。然后以Tdatasource對象為中介,用數據感知組件向用戶顯示數據庫的內容并接受用戶的查詢和修改等操作。
3.2.4 SQL語言在Delphi中的應用
在Delphi中使用SQL語言非常方便,一般來說,都是通過Tquery組件來使用SQL語言的。可以在TQuery組件的SQL屬性中設置SQL語句。設計程序時,在該組件的屬性對話框中選擇SQL屬性,單擊帶省略號的按鈕,就可以打開String List Editor對話框,然后我們就可以在對話框中添加SQL語句。還可以使用Delphi的SQL Builder來自動生成SQL語句,這樣可以避免手工編寫SQL而可能造成的語法錯誤。
靜態SQL語句在程序設計時便已固定下來,它不包含任何參數和變量。動態SQL語句,也被稱作參數化的語句,在其中間包含著表示字段名或表名的參數,例如下面的語句是一條動態SQL語句:
Select * From Students Where StudentCode =: StudentCode;其中的變量StudentCode便是一個參數變量,它由一個冒號引導,在程序運行過程中,必須要為該參數賦值,該條SQL語句才能正確執行,每次運行應用程序時可以為該參數變量賦予不同的值。為參數賦值有三種方法:
①根據參數在SQL語句中出現的順序,設置TQuery部件的Params屬性值為參數賦值。
②直接根據SQL語句中各參數的名字,調用ParamByName方法來為各參數賦值。③將TQuery部件的DataSource屬性設置為另一個數據源,這樣將另一個數據源中與當前TQuery部件的SQL語句中的參數名相匹配的字段值賦給其對應的參數。利用這種方法也能實現所謂的連接查詢,創建主要—明細型數據庫應用。在程序運行過程中,要想設置TQuery部件的SQL屬性,必須首先調用Close方法,關閉TQuery部件,然后再調用Clear方法清除SQL屬性中現存的SQL命令語句,最后再調用Add方法為SQL屬性設置新的SQL命令語句。例如: Query1.Close {關閉Query1)Query1.SQL.Clear {清除SQL屬性中的SQL命令語句} Query1.SQL.Add(‘Select * From Students‘);Query1.SQL.Add(‘ Where Name =“Lucy” ‘);
在為TQuery部件設置SQL屬性時調用Close方法總是很安全的,如果TQuery部件已經被關閉了,調用Close方法時不會產生任何影響。在應用程序中為SQL屬性設置新的SQL 命令語句時,必須要調用Clear方法以清除SQL屬性中現存的SQL命令語句,如果不調用Clear方法,便調用Add方法向SQL屬性中設置SQL命令語句,那么新設置的SQL命令語句會追加在現存SQL命令語句后面,在程序運行時常常會出現出乎意料的查詢結果甚至程序無法運行下去。
在這里要特別注意的,一般情況下TQuery部件的SQL屬性只能包含一條完整的SQL語句,它不允許被設置成多條SQL語句。當然有些數據庫服務器也支持在TQuery部件的SQL屬性中設置多條SQL語句,只要數據庫服務器允許這樣,我們在編程時可以為 SQL 屬性設置多條SQL語句。
在為TQuery部件設置完SQL屬性的屬性值之后,也即編寫好適當的SQL程序之后,可以有多種方式來執行SQL程序。
在設計過程中,設置完TQuery部件的SQL屬性之后將其Active屬性的值置為True,這樣便可以執行SQL屬性中的SQL程序,如果應用中有與TQuery部件相連的數據瀏覽部件(如TDDGrid TDBEdit等)那么在這些數據瀏覽部件中會顯示SQL程序的執行結果。
在應用程序運行過程中,通過程序調用TQuery部件的Open方法或ExecSQL 方法可以執行其SQL屬性中的SQL程序。Open方法和ExecSQL方法是不一樣的。Open方法只能用來執行SQL語言的查詢語句(Select命令),并返回一個查詢結果集,而ExecSQL方法還可以用來執行其它常用的SQL語句(如INSERT, UPDATE, DELETE等命令),例如:
Query1.Open(這樣會返回一個查詢結果集)如果調用Open方法,而沒有查詢結果時,會出錯。此時應該調用ExecSQL 方法來代替Open方法。如: Query1.ExecSQL(沒有返回結果)當然在設計應用程序時,程序設計人員是無法確定TQuery部件中的SQL 語句是否會返回一個查詢結果的。對于這種情況應當用Try?Except模塊來設計程序。在 Try 部分調用Open方法,而在Except部分調用ExceSQL方法,這樣才能保證程序的正確運行。
Delphi中用ADOQuery來使用SQL語句同樣十分方便。在ADOQuery組件中首先通過ConnectionString屬性值來聯接數據源,然后就通過雙擊SQL?屬性值來寫入SQL語句。在Delphi中調用數據庫,就可以調用ADOQuery組件,通過修改其中的SQL?屬性中的SQL語句來實現對數據庫的各項操作。
值得注意的是,ADOQuery組件只有在激活的情況下才可以被正確地使用,這樣就提出了一個問題,也就是說,在每次修改ADOQuery組件的SQL?屬性時都必須先行進行關閉,待清除掉SQL?中所有的SQL語句后才可以添加新的SQL語句。而且,在每一次修改完成以后,還應該記得重新將ADOQuery激活。其它的使用方法與TTQuery有許多的相似之處。§3.3 Access 簡介
建立一個數據庫我們有多種選擇,現在市場上有各種各樣的數據庫,而且每一種數據庫都有其自身的特點,不能說哪一種更好,只能在其中尋找一種能更好地適應系統需求、更好地滿足用戶的要求以及適應開發人員的習慣。在本系統中,做為圖書倉庫管理系統是一個比較小的應用系統,它所產生和處理的數據量也比較小。因此,沒有必要使用像SQL Server和Oracle這樣的大型數據庫。我首先想到的數據庫是Borland公司的Paradox數據庫。另外,Microsoft Office中的Access數據庫在計算機上的應用比較普及,是開發小型數據庫系統的比較理想的選擇,所以,在本系統中我選擇了Access數據庫。
Access做為一個數據庫管理系統,它被集成在Microsoft Office中。Access數據庫處理的基本結構,采取關系型數據庫模式。與其他的數據庫系統相比,Access更加簡單易學,一個普通的計算機用戶可以很快地掌握它。Access 2000的功能十分強大,利用它可以方便地實現對信息保存、維護、查詢、統計、打印、交流、發布,而且它可以十分方便地與Office其他組件交流數據,這些功能對一個一般用戶而言已經足夠了 第四章 系統總體設計
軟件系統的總體設計大約要經歷可行性分析和項目開發計劃,需求分析,概要設計,詳細設計,編碼,測試以及維護等七個階段。可行性分析和項目開發計劃在前面已經敘述,下面所要做的是進行軟件需求分析,概要設計和詳細設計。編碼過程將在下一節論述,而測試和維護過程不在本文敘及。§4.1 系統需求分析
在經過前一階段的分析之后,我確定了我的開發課題為圖書倉庫管理。現在所要做的是要準確定義系統必須做什么以及系統必須具備的功能。
軟件需求分析中我采用結構化分析方法(Structured Analysis,簡稱SA),SA是面向數據流進行需求分析的方法,像所有的軟件分析方法(如面向對象分析方法、IDEF方法等等)一樣,SA也是一種建模活動,它使用簡單易讀的符號,根據軟件內部數據傳遞、變換的關系,自頂向下逐層分解,描繪滿足功能要求的軟件模型。
在系統中我采用數據流圖(DFD)這種半形式化的描述方式表達需求。它是一種功能模型,以圖形的方式描繪數據在系統中流動和處理的過程,只反映系統必須完成的邏輯功能。它有四種基本圖形符號: ◆ →:箭頭,表示數據流; ◆ 〇:圓或橢圓,表示加工; ◆ ═:雙杠,表示數據存儲;
◆ □:方框,表示數據的源點或終點。
為了表達較為復雜問題的數據處理過程,用一張數據流圖是不夠的,要按照問題的層次結構進行逐步分解,并以一套分層的數據流圖反映這種結構關系。在這里我一共使用了三層數據流圖,即頂層圖,0層圖和1層圖(也是底層圖)。在多層數據流圖中,頂層流圖僅包含一個加工,它代表被開發系統,它的輸入流是該系統的輸入數據了,輸出流是該系統的輸出數據;底層流圖是指其加工不需要再做分解的數據流圖,中間層流圖表示對其上層父圖的細化,它的每一步加工可能繼續細化成子圖。
經過對系統的分析首先得到系統的頂層DFD,如下: 一步細化得到系統的0層DFD,如下:
再進一步細化每一個數據加工功能,得到系統的1層DFD圖。
在這里只給出有關入庫管理和出庫管理的1層數據流圖,它們是系統的關鍵部分,也是主要的部分。通過以上對數據流圖的分析之后,我們已大體地了解了系統的功能和目標,接下來所要做的就是系統功能模塊的劃分和數據庫的設計,也就是系統的概要設計。§4.2 系統概要設計
在軟件需求分析階段,搞清楚了軟件“做什么”的問題,形成了目標系統的邏輯模型。現在我們所要做的就是要把軟件“做什么”的邏輯模型變換為“怎么做”的物理模型,即著手實現軟件的需求。首先,我們需要描述的是系統的總的體系結構。
4.2.1 系統結構設計
系統的概要設計中最重要的就是系統的模塊化。模塊化是指解決一個復雜問題時自項向下逐層把軟件系統劃分成若干個模塊的過程。每個模塊完成一個特定的功能,所有的模塊按某種方法組織起來,成為一個整體,完成整個系統所要求的功能。
將系統劃分為多個模塊是為了降低軟件系統的復雜性,提高可讀性、可維護性,但模塊的劃分不能是任意的,應盡量保持其獨立性。也就是說,每個模塊只完成系統要求的獨立的子功能,并且與其他模塊的聯系最少且接口簡單,即盡量做到高內聚低耦合,提高模塊的獨立性,為設計高質量的軟件結構奠定基礎。在系統的概要設計中我采用結構化設計(Structure Design,簡稱SD),SD以需求分析階段產生的數據流圖DFD為基礎,按一定的步驟映射成軟件結構。我首先將整個系統化分為幾個小問題,小模塊,在系統中,我設計了用戶管理、庫存管理、入庫管理、出庫管理、員工管理和供應商管理6個小模塊。然后,進一步細分模塊,添加細節。比如,用戶管理我又將其分為用戶注冊、用戶注銷、密碼修改;庫存管理分為庫存記錄查詢、庫存記錄修改、庫存記錄打印等等。以下就是系統的結構圖:(在這里為了表達方便我將結構圖分開來表達。)
在得到系統的第一層功能模塊圖后,經過進一步地細化,得一系統的子功能模塊圖:
4.2.2 數據庫設計
在信息世界中,信息從客觀事物出發流經數據庫,通過決策機構最后又回到客觀世界,信息的這一循環經歷了三個領域:信息世界,數據世界,現實世界。現實世界的事物反映到人的頭腦中,人的大腦對它有個認識過程,經過分析(選擇、命名、分類等)進入信息世界。這些信息再進一步加工、編碼,然后進數據世界,而軟件系統的開發工作需要考慮這兩個方面的問題,也就是要考慮系統開發所需要的數據,以及如何對這些數據進行操作。這兩個問題貫穿了整個軟件系統的開發過程,這也就是數據庫的設計問題,軟件設計的一個核心。4.2.2.1 ER圖設計
在系統設計的開始,我首先考慮的是如何用數據模型來數據庫的結構與語義,以對現實世界進行抽象。目前廣泛使用的數據模型可分為兩種類型,一種是獨立于計算機系統的“概念數據模型”,如“實體聯系模型”;另一種是直接面向數據庫邏輯結構的“結構數據模型”。在本系統中我采用“實體聯系模型”(ER模型)來描述數據庫的結構與語義,以對現實世界進行第一次抽象。ER模型直接從現實世界抽象出實體類型及實體間聯系,然后用ER圖來表示數據模型。它有兩個明顯的優點:接近于人的思維,容易理解;與計算機無關,用戶容易接受。但ER模型只能說明實體間語義的聯系,不能進一步說明詳細的數據結構,它只是數據庫設計的第一步。
ER圖是直觀表示概念模型的工具,它有四個基本成分: ◆ 矩形框,表示實體類型(考慮問題的對象)。◆ 菱形框,表示聯系類型(實體間的聯系)。
◆ 橢圓形框,表示實體類型和聯系類型的屬性。對于關鍵碼的屬性,在屬性名下劃一橫線。
◆直線,聯系類型與其涉及的實體類型之間以直線連接。
本系統為圖書倉庫管理,主要管理圖書的入庫、出庫以及庫存等事項。倉庫根據需要可以查詢圖書供應商的信息,同時還需要了解在入庫和出庫中員工的參與情況。依據倉庫管理的實際情況,考慮了多方面的因素以后,確定系統的ER圖如下:
(為了表達的方便,在這里我沒有在一張圖上表達出所有的關系,而是用一張總體ER圖,和幾張實體屬性關系圖來表達數據庫的結構。)
在該數據庫中,我設計了三個實體,分別是庫存、員工和供應商以及兩個聯系類型入庫和出庫。在本系統中庫存是核心,也是基本,沒有了庫存其它的也就沒有什么意義了。員工記錄的添加是考慮到責任問題,也就是說,在倉庫管理的實際運用中,出現了責任不清的現象,特別是由于倉庫的進出圖書數量都比較大時產生了一系列問題,所以在設計數據庫時,我特別考慮到這一點,加入了員工記錄這一實體。供應商信息的添加主要出于對圖書來源問題的思考。通過添加供應商信息可以比較清楚地了解圖書的進貨渠道,從圖書的質量到供應商的信譽都可以進行了解,同時可以為以后的圖書進購提供一定有用的信息。
入庫聯系類型將庫存信息、供應商信息和員工信息聯系在一起,可以方便地實現三個實體之間的聯接,而出庫聯系類型則將庫存信息和員工信息較好地聯接起,同時這兩個聯系類型又都具有各自特有的屬性。下面就是各實體及聯系類型的屬性圖:(帶#號的屬性為關鍵字段)4.2.2.2 數據庫表格設計
在完成系統的ER圖之后,需要將ER模型轉化為關系模型,也就是說,要設計出數據庫所需要的表格。在這里,我選用的是關系數據庫。因為關系數據庫中的二維表格可以很清楚地描述數據之間的聯系。
在這里不得不提到一個概念——范式。其實在上一節的ER圖設計中,已經運用了范式的思想,不僅如此,在數據庫的表格設計中更離不開范式的思想,它是數據庫設計的基礎,如果不注意這個問題將會導致一系列問題的出現。
我在系統中定義的表格都嚴格地按照范式的思想和要求去完成,數據庫中的所有表格都達到了三范式的要求。根據系統ER圖,針對本系統的特點,在對所搜集的數據進行規范化之后,定義了如下六張表格,分別是庫存信息表,入庫信息表,出庫信息表,員工信息表,供應商信息表和密碼信息表。通過對這六張表格的操作可以較好地完成系統設計的各項功能,六張表格之間有著不同程度的聯系。(說明:在以下數據表中,K代表主鍵,#代表外鍵,字段值不為空。)BookRecord 表(庫存信息表)
字段名稱 數據類型 說明 K BookID 數字 圖書編號 BookName 文本 圖書名 Author 文本 作者 Publisher 文本 出版社 PubDate 日期/時間 出版日期 Price 貨幣 價格 BookType 文本 圖書類型 Number1 數字 庫存數量 Addation 文本 備注 圖4.13 庫存信息表 庫存信息表主要用于記錄倉庫中現存放的所有圖書的詳細信息,包括圖書編號、書名、作者、出版社、圖書類型等有關圖書的各類信息,它即是該數據庫的主表,也是系統主界面的主要內容。
在該表中圖書編號是主鍵,它按圖書入庫的先后次序來編寫,每當有圖書入庫,系統自動給出圖書編號,這樣我們按圖書編號來查找圖書是比較方便的。考慮到編號比較難于記憶,所以使用了出版社和圖書類型兩個字段,在系統中我提供了出版社和圖書類型的分類查找,而且全部采用自動生成,每當系統中有新的出版社類型和圖書類型,彈出菜單會自動添中新類型,這樣就可以比較方便地實現按出版社和按圖書類型查找。此外,庫存數量也是一個比較關鍵的字段,該字段是在系統初始化時就給定的,每當有圖書入庫或出庫操作,系統就會自動修改圖書的庫存數量,以保持數據的一致性。做為備注有一點說明,我的數據庫中備注的數據類型是文本,而不是備注類型,主要考慮到該字段的長度并不大,而且在Delphi中文本數據類型的處理也比較方便一點。Employee 表(員工信息表)
字段名稱 數據類型 說明 K EmployeeID 數字 員工編號 EmployeeName 文本 員工姓名 Sex 文本 性別
BornDate 日期/時間 出生日期 Grade 文本 職稱
WorkDate 日期/時間 工作日期 Telephone 文本 聯系電話 Address 文本 聯系地址
圖4.14 員工信息表
員工信息表主要用于記錄有關員工的各類信息,包括姓名、職稱、出生日期、聯系電話、聯系地址等。它主要用來為系統提供員工的有關信息,因為在系統中,入庫和出庫操作均與員工有著一定的聯系,在查詢入庫信息和出庫信息時,有時需要查找有關此項記錄有關的員工信息,在系統中我是通過入庫記錄與員工記錄(出庫記錄和員工記錄)之間的聯接查詢來完成的。另外,作為一個倉庫也有必要了解其所屬員工的一些基本情況,以便查詢。Shopkeeper 表(供應商信息表)
字段名稱 數據類型 說明 K ShopkeeperID 數字 供應商編號 ShopkeeperName 文本 供應商姓名 Address 文本 地址 PostNo 數字 郵編
OfficePhone 文本 辦公電話 HomePhone 文本 住宅電話 Email 文本 E-mail PayType 文本 付款方式
圖4.15 供應商信息表
供應商信息表主要用于記錄有關供應商的各類信息,包括姓名、地址、電話、付款方式等。它主要用來為系統提供供應商的有關信息,在系統中入庫記錄是與供應商記錄相聯系的,通過入庫記錄可以查找相關的供應商信息。在供應商信息中,考慮當實際情況,我特別加入了Email和付款方式這兩個字段,因為在當今信息世界中,多種多樣的通訊方式和多種多樣的付款方式是必然的,是數據庫中必須與以記錄。
InRecord 表(入庫信息表)
字段名稱 數據類型 說明 K InID 數字 入庫編號 # BookID 數字 圖書編號 # EmployeeID 數字 員工編號 # ShopkeeperID 數字 供應商編號 Number 數字 入庫數量 BuyDate 日期/時間 入庫日期
圖4.16 入庫信息表
OutRecord 表(出庫信息表)
字段名稱 數據類型 說明 K OutID 數字 出庫編號 # BookID 數字 圖書編號 # EmployeeID 數字 員工編號 Number2 數字 出庫數量 OutDate 日期/時間 出庫日期
圖4.17 出庫信息表
入庫信息表主要用于記錄有關入庫的詳細信息,包括入庫數量、入庫日期以及圖書、員工、供應商三方的編號,以便查詢。出庫信息表主要用于記錄有關出庫的詳細信息,包括出庫數量、出庫日期以及圖書、員工的編號。出庫信息表和入庫信息表一樣,其實它們都屬于聯系類型,系統通過這兩個表可以聯接上其它的表為用戶提供多種條件的聯接查詢。值得提出的一點是入庫記錄和出庫記錄的添加不僅僅是單表操作,由于它們都與庫存記錄相聯系,所以,無論您是添中入庫記錄還是添加出庫記錄,都必須同時修改庫存記錄,以保持數據的一致性,否則將引發系統出錯而這些我都讓其在系統中自動完成。無論您是添加入庫記錄,還是添加出庫記錄,系統都將自動修改庫存中圖書的數量,而且,在您出庫的數量大于庫存數量時,系統還會自動提示錯誤,這樣就可以防止一定錯誤的發生。在入庫信息表和出庫信息表中我還定義了幾個外鍵,它提供了一種表示幾個關系聯系的方法。比如,系統中通過在入庫信息表中定義的外鍵 BookID、EmployeeID和ShopkeeperID可以將庫存信息表、員工信息表和供應商信息表聯系在一起,從而方便地實現聯接查詢,而且,引入外鍵的定義是實體完整性約束的一個主要方面。
Key 表(密碼信息表)
字段名稱 數據類型 說明 K KeyName 文本 用戶姓名 KeyNo 文本 用戶密碼 圖4.18 密碼信息表
密碼信息表主要用于記錄所有的用戶名和用戶密碼。它是在用戶登陸時用來確定用戶和密碼的正確性,以防止非法用戶登陸。
通過以上設計已經完成了系統的概要設計,當我們有了系統的功能模塊圖和數據庫之后,就需要著手去實現每一個模塊,為每一個功能設計程序流程圖,這也就是系統的詳細設計。§4.3 系統詳細設計
在前面的概要設計中,已將系統劃分為多個模塊,并將它們按照一定的原則組裝起來,同時確定了每個功能及模塊之間的外部接口。現在所要做的就是確定每個模塊具體執行過程,也可以說是“過程設計”。
在處理過程設計時我采用的是結構化程序設計(簡稱SP)方法。需要指出的是系統的詳細設計并不是指具體的編程序,而是將概要設計階段產生的系統功能模塊圖細化成很容易產生程序的圖紙。因此詳細設計的結果基本決定了最終程序的質量。為軟件的質量,延長軟件的生存期,軟件的可測試性、可維護性提供重要的保障。詳細設計的目標不僅是邏輯上正確地實現每個模塊的功能,還應使設計出的處理過程清晰易讀。
由前一階段產生的系統功能模塊圖,我為系統的主要部分設計了如下程序流程圖:通過以上步驟,基本上完成了對整個系統的總體設計,接下來所要做的就是軟件的編碼工作。系統總體設計的好壞直接影響著下一步工作,只有在這一階段設計出好的模塊圖和程序流程圖,才能更有利于編碼,產生好的軟件系統。
第五章 系統應用程序設計 §5.1 系統窗體模塊組成 §5.2 數據模塊窗體的設置
在編寫數據庫應用程序時,經常要遇到這樣的情況,即好多組件、窗體同時訪問相同的數據源,如果為每一個組件或者窗體都設置一個數據源將是十分耗時的工件,而且要保證這些數據源的確是相同的也需花一番功夫。那么,能不能將這些數據源集中管理,最好是做成一個統一的模塊,需要時就將該模塊引入而不必直接操作數據源本身呢?數據模塊(DataModule)是解決這個問題最好的答案。簡單說來,數據模塊是用來集中管理數據源的一個窗體,該窗體可被需要的地方隨時引入。
圖5.2給出了本程序的數據模塊(datamoduleform)窗體圖,除報表窗體外所有的數據存取組件和數據源組件都在此數據模塊中進行了定義。值得一提的是,設置了數據庫Database組件,該組件引入了系統所需的唯一的數據庫tsxs,Database組件的DatabaseName屬性設置為tsckgl。tsxs數據庫已在ODBC配置程序中進行了設置。其他的數據存取組件都是基于此數據庫組件創建的,這樣做的好處是,當數據庫的別名或者其他信息改變之后,只需修改Tdatabase組件的AliasName屬性即可。
另外,在本系統的數據模塊窗體圖中,我大多采用的AODQuery組件而沒有采用BDE組,這主要是基于對ADO組件的了解。在Delphi的學習中我對ADO組件了解的更加清楚,使用也較BDE更為熟練,而且,ADO組件的功能也較BDE更為強大,所以在這里大多采用ADO組件來進行數據庫聯接。同時我也使用了BDE組件中的Table,因為在某些時候BDE有著其自身特有的優越性。主窗體功能模塊的實現 file://主窗體程序代碼
public file://在程序的起始部分,定義快捷按鈕點擊事件 Procedure Popup1Handler(Sender:Tobject);Procedure Popup2Handler(Sender:TObject);********************************************************************** procedure Tmainform.Popup1Handler(Sender: TObject);begin file://快捷按鈕1(點“按出版社分類”按鈕產生)的點擊事件 with datamoduleform.MainQuery do begin file://打開數據模塊窗體的MainQuery,對BookRecord表進行操作 close;file://關閉MainQuery SQL.Clear;file://清除SQL屬性中的SQL命令語句
SQL.Add(‘select * from BookRecord where Publisher=:Pub‘);file://添加新的SQL語句
Parameters.ParamByName(‘Pub‘).Value:=(Sender as TMenuItem).Caption;open;file://重新打開MainQuery end;end;********************************************************************** procedure Tmainform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3,s4,s5 :String;file://設立5個變量以方便實現模糊查詢 begin file://主窗口庫存查詢按鈕事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);
SQL.Add(‘where BookID Like :BookID and BookName Like :Name and Author Like :Author and Publisher Like :pub and BookType Like :BookType‘);file://使用Like語句來實現模糊查詢
if Edit1.Text<>‘‘ then s1:=‘%‘+Edit1.Text+‘%‘ else s1:=‘%‘;
Parameters.ParamByName(‘BookID‘).Value:=s1;file://給變量s1賦值
if Edit2.Text<>‘‘ then s2:=‘%‘+Edit2.Text+‘%‘ else s2:=‘%‘;
Parameters.ParamByName(‘Name‘).Value:=s2;file://給變量s2賦值
if Edit3.Text<>‘‘ then s3:=‘%‘+Edit3.Text+‘%‘ else s3:=‘%‘;
Parameters.ParamByName(‘Author‘).Value:=s3;file://給變量s2賦值
if Edit4.Text<>‘‘ then s4:=‘%‘+Edit4.Text+‘%‘ else s4:=‘%‘;
Parameters.ParamByName(‘Pub‘).Value:=s4;file://給變量s2賦值
if Edit5.Text <>‘‘ then s5:=‘%‘+Edit5.Text+‘%‘ else s5:=‘%‘;
Parameters.ParamByName(‘BookType‘).Value:=s5;file://給變量s2賦值 open;if FieldValues[‘BookID‘]=NULL file://判斷是否找到記錄 then begin Messagedlg(‘沒有找到你所需要的記錄!‘,mtInformation,[mbOK],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit4.Text:=‘‘;Edit5.Text:=‘‘;close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);file://這里相當于一個刷新功能 open;end;end;end;********************************************************************** procedure Tmainform.SpeedButton3Click(Sender: TObject);begin file://庫存表刷新按鈕事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);open;end;end;********************************************************************** procedure Tmainform.SpeedButton11Click(Sender: TObject);var PopupItem:TMenuItem;begin file://自動生成快捷按鈕1的內容 with datamoduleform.BookQuery do begin file://從數據庫中選擇出版社類型 close;SQL.Clear;SQL.Add(‘select distinct Publisher from BookRecord‘);open;PopupMenu1:=TPopupMenu.Create(Self);file://自動生成快捷菜單 PopupMenu1.AutoHotkeys:=maManual;file://自定義熱鍵 while Not Eof do begin file://根據出版社內容生成菜單子項 PopupItem:=TMenuItem.Create(Self);PopupItem.Caption:=FieldByName(‘Publisher‘).AsString;PopupMenu1.Items.Add(PopupItem);PopupItem.onClick:=Popup1Handler;file://確定菜單子項的點擊事件 Next;end;end;PopupMenu1.Popup(384,67);file://在指定位置顯示快捷菜單1 end;********************************************************************** procedure Tmainform.FormActivate(Sender: TObject);begin file://系統初始化,在進入mainform時自動添加數據源 mainform.DBGrid1.DataSource:=datamoduleform.MainSource;mainform.DBNavigator1.DataSource:=datamoduleform.MainSource;mainform.DBGrid2.DataSource:=datamoduleform.EmpSource;mainform.DBNavigator2.DataSource:=datamoduleform.EmpSource;mainform.DBGrid3.DataSource:=datamoduleform.ShopSource;mainform.DBNavigator3.DataSource:=datamoduleform.ShopSource;mainform.DBGrid4.DataSource:=datamoduleform.InSource;mainform.DBNavigator4.DataSource:=datamoduleform.InSource;mainform.DBGrid5.DataSource:=datamoduleform.OutSource;mainform.DBNavigator5.DataSource:=datamoduleform.OutSource;end;********************************************************************** procedure Tmainform.FormCreate(Sender: TObject);begin file://系統初始化,定義界面大小,以適應不同分辯率 Width:=800;Height:=600;end;********************************************************************** procedure Tmainform.Timer1Timer(Sender: TObject);begin file://在狀態欄顯示時間 StatusBar1.Panels[2].Text:=DateToStr(Date);StatusBar1.Panels[4].Text:=TimeToStr(Time);end;§5.4 入庫、出庫窗體模塊的實現
圖5.4 系統入庫管理窗體
圖5.5 系統出庫管理窗體 procedure Tinoutform.SpeedButton4Click(Sender: TObject);begin file://入庫管理查找按鈕事件
with datamoduleform.BookQuery do file://入庫查詢處理 begin close;SQL.Clear;SQL.Add(‘select * from BookRecord where BookID=:BookID‘);
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;open;if FieldValues[‘BookID‘]<>NULL then begin Edit1.Text:=‘‘;
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;Edit6.Text:=FieldValues[‘BookName‘];file://顯示圖書名 Edit6.ReadOnly:=true;Edit6.Color:=clMenu;file://設置顯示框不可更改屬性
Edit7.Text:=FieldValues[‘Author‘];Edit7.ReadOnly:=true;Edit7.Color:=clMenu;Edit8.Text:=FieldValues[‘Publisher‘];Edit8.ReadOnly:=true;Edit8.Color:=clMenu;Edit9.Text:=FieldValues[‘PubDate‘];Edit9.ReadOnly:=true;Edit9.Color:=clMenu;Edit10.Text:=FieldValues[‘Price‘];Edit10.ReadOnly:=true;Edit10.Color:=clMenu;Edit11.Text:=FieldValues[‘BookType‘];Edit11.ReadOnly:=true;Edit11.Color:=clMenu;Edit12.Text:=FieldValues[‘Number1‘];Edit12.ReadOnly:=true;Edit12.Color:=clMenu;If FieldValues[‘Addation‘]<>NULL then Edit25.Text:=FieldValues[‘Addation‘]
else Edit25.Text:=‘‘;
Edit25.ReadOnly:=true;Edit25.Color:=clMenu;end else begin file://在沒有查找到的情況下,清空所有顯示框 Edit1.ReadOnly:=false;Edit1.Text:=‘‘;Edit1.Color:=clMenu;
Edit6.ReadOnly:=false;Edit6.Text:=‘‘;Edit6.Color:=clMenu;
Edit7.ReadOnly:=false;Edit7.Text:=‘‘;Edit7.Color:=clMenu;
Edit8.ReadOnly:=false;Edit8.Text:=‘‘;Edit8.Color:=clMenu;Edit9.ReadOnly:=false;Edit9.Text:=‘‘;Edit9.Color:=clMenu;
Edit10.ReadOnly:=false;Edit10.Text:=‘‘;Edit10.Color:=clMenu;
Edit11.ReadOnly:=false;Edit11.Text:=‘‘;Edit11.Color:=clMenu;
Edit12.ReadOnly:=false;Edit12.Text:=‘‘;Edit12.Color:=clMenu;Edit25.ReadOnly:=false;Edit25.Text:=‘‘;Edit25.Color:=clMenu;
MessageDlg(‘沒有找到你所需要的記錄!‘,mtInformation,[mbOK],0);Edit13.Text:=‘‘;Edit13.SetFocus;end;end;with datamoduleform.InQuery do file://自動入庫編號的獲取 begin close;SQL.Clear;SQL.Add(‘select * from InRecord where InID>=All(select InID from InRecord)‘);
open;file://找到入庫編號中最大的一個 Edit26.ReadOnly:=false;Edit26.Text:=FieldValues[‘InID‘]+1;file://最大的入庫編號加1形成新的入庫編號
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;file://設置編號的不可更改性 end;end;********************************************************************** procedure Tinoutform.SpeedButton1Click(Sender: TObject);var s:integer;begin file://入庫管理添加按鈕事件 if Edit1.Text<>NULL then MessageDlg(‘請輸入完整的入庫信息和圖書信息,然后單擊確定按鈕。‘, mtInformation,[mbok],0)else begin if(Edit2.Text=‘‘)or(Edit3.Text=‘‘)or(Edit4.Text=‘‘)or(Edit5.Text=‘‘)then begin MessageDlg(‘請輸入完整的入庫信息!‘,mtInformation,[mbok],0);Edit2.SetFocus;end else begin with datamoduleform.InQuery do file://將找到的圖書信息顯示 begin close;SQL.Clear;SQL.Add(‘insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)‘);file://向入庫信息表中插入記錄
Parameters.ParamByName(‘InID‘).Value:=Edit26.Text;file://向Edit框取值
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;
Parameters.ParamByName(‘EmpID‘).Value:=Edit2.Text;
Parameters.ParamByName(‘ShopID‘).Value:=Edit3.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘InDate‘).Value:=Edit5.Text;execSQL;end;Edit12.ReadOnly:=False;S:=StrToInt(Edit12.Text)+StrToInt(Edit4.Text);file://計算入庫后庫存圖書數量
Edit12.Text:=IntToStr(s);file://將修改后的庫存圖書數量顯示 Edit12.ReadOnly:=true;with datamoduleform.BookQuery do file://修改庫存記錄中圖書數量
begin close;SQL.Clear;SQL.Add(‘update BookRecord set Number1=:Number where BookID=:BookID‘);
Parameters.ParamByName(‘Number‘).Value:=s;
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;execSQL;file://提交SQL語句
MessageDlg(‘記錄已成功添加!‘,mtInformation,[mbOK],0);Edit13.SetFocus;end;end;end;end;********************************************************************** procedure Tinoutform.SpeedButton2Click(Sender: TObject);begin file://入庫管理確定按鈕事件
if(Edit2.Text=‘‘)or(Edit3.Text=‘‘)or(Edit4.Text=‘‘)or(Edit5.Text=‘‘)
or(Edit6.Text=‘‘)or(Edit7.Text=‘‘)or(Edit8.Text=‘‘)or(Edit9.Text=‘‘)
or(Edit10.Text=‘‘)or(Edit11.Text=‘‘)or(Edit25.Text=‘‘)then begin file://判斷輸入信息的完整性
MessageDlg(‘請輸入所需的全部入庫信息!‘,mtInformation,[mbok],0);Edit2.SetFocus;end else begin with datamoduleform.InQuery do file://入庫信息添加 begin close;SQL.Clear;SQL.Add(‘insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)‘);file://向入庫信息表中插入記錄
Parameters.ParamByName(‘InID‘).Value:=Edit26.Text;
Parameters.ParamByName(‘BookID‘).Value:=Edit1.Text;Parameters.ParamByName(‘EmpID‘).Value:=Edit2.Text;
Parameters.ParamByName(‘ShopID‘).Value:=Edit3.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘InDate‘).Value:=Edit5.Text;execSQL;end;with datamoduleform.BookQuery do begin close;SQL.Clear;file://在完成入庫信息的添加后,修改庫存記錄 SQL.Add(‘insert into BookRecord values(:BookID,:BookName,:Author, :Publisher,:PubDate,:Price,:BookType,:Number,:Addration)‘);
Parameters.ParamByName(‘BookID‘).Value:=Edit1.Text;Parameters.ParamByName(‘BookName‘).Value:=Edit6.Text;Parameters.ParamByName(‘Author‘).Value:=Edit7.Text;
Parameters.ParamByName(‘Publisher‘).Value:=Edit8.Text;
Parameters.ParamByName(‘PubDate‘).Value:=Edit9.Text;Parameters.ParamByName(‘Price‘).Value:=Edit10.Text;
Parameters.ParamByName(‘BookType‘).Value:=Edit11.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘Addration‘).Value:=Edit25.Text;execSQL;end;MessageDlg(‘記錄添加成功!‘,mtInformation,[mbok],0);end;end;********************************************************************** procedure Tinoutform.SpeedButton11Click(Sender: TObject);begin file://新書入庫按鈕事件
Edit13.Text:=‘‘;Edit13.Color:=clMenu;with datamoduleform.InQuery do file://自動入庫編號的獲取 begin close;SQL.Clear;SQL.Add(‘select * from InRecord where InID>=All(select InID from InRecord)‘);open;Edit26.Text:=FieldValues[‘InID‘]+1;Edit26.ReadOnly:=true;Edit26.Color:=clMenu;end;with datamoduleform.BookQuery do file://自動圖書編號的獲取 begin close;SQL.Clear;SQL.Add(‘select * from BookRecord where BookID>=All(select BookID from BookRecord)‘);file://找到庫存圖書編號中最大的一個 open;Edit1.ReadOnly:=false;Edit1.Text:=FieldValues[‘BookID‘]+1;file://顯示自動生成的圖書編號
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;end;
Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit4.Text:=‘‘;Edit5.Text:=‘‘;
Edit6.ReadOnly:=false;Edit6.Text:=‘‘;Edit6.Color:=clWindow;Edit7.ReadOnly:=false;Edit7.Text:=‘‘;Edit7.Color:=clWindow;
Edit8.ReadOnly:=false;Edit8.Text:=‘‘;Edit8.Color:=clWindow;
Edit9.ReadOnly:=false;Edit9.Text:=‘‘;Edit9.Color:=clWindow;
Edit10.ReadOnly:=false;Edit10.Text:=‘‘;Edit10.Color:=clWindow;Edit11.ReadOnly:=false;Edit11.Text:=‘‘;Edit11.Color:=clWindow;
Edit12.ReadOnly:=false;Edit12.Text:=‘‘;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=‘‘;Edit25.Color:=clWindow;end;procedure Tinoutform.SpeedButton22Click(Sender: TObject);var s:integer;begin file://出庫管理確定按鈕事件
if(Edit24.Text=‘‘)or(Edit27.Text=‘‘)or(Edit28.Text=‘‘)then begin MessageDlg(‘請輸入完整的出庫信息!‘,mtInformation,[mbok],0);Edit24.SetFocus;end else begin if Edit27.Text>Edit21.Text file://檢查出庫數量是否小于庫存數量 then begin MessageDlg(‘庫存中的圖書數量不夠!‘,mtInformation,[mbok],0);Edit27.Text:=‘‘;Edit27.SetFocus;end else begin with datamoduleform.OutQuery do begin close;SQL.Clear;SQL.Add(‘insert into OutRecord values(:OutID,:BookID,:EmpID, :Number,:OutTime)‘);file://添加出庫記錄
Parameters.ParamByName(‘OutID‘).Value:=Edit23.Text;Parameters.ParamByName(‘BookID‘).Value:=Edit14.Text;Parameters.ParamByName(‘EmpID‘).Value:=Edit24.Text;Parameters.ParamByName(‘Number‘).Value:=Edit27.Text;Parameters.ParamByName(‘OutTime‘).Value:=Edit28.Text;execSQL;end;
第四篇:圖書倉庫管理系統的設計
圖書倉庫管理系統的設計
摘 要
本系統主要完成對圖書倉庫的庫存管理,包括圖書入庫、出庫、庫存,員工信息,供應商信息以及密碼管理等六個方面。系統可以完成對各類信息的瀏覽、查詢、添加、刪除、修改、報表等功能。
系統的核心是入庫、庫存和出庫三者之間的聯系,每一個表的修改都將聯動的影響其它的表,當完成入庫或出庫操作時系統會自動地完成庫存的修改。查詢功能也是系統的核心之一,在系統中即有單條件查詢和多條件查詢,也有精確查詢和模糊查詢,系統不僅有靜態的條件查詢,也有動態生成的條件查詢,其目的都是為了方便用戶使用。系統有完整的用戶添加、刪除和密碼修改功能,并具備報表打印功能。
系統采用Microsoft Office中的Access 2000來設計數據庫,并使用當前優秀的開發工具—Delphi 6.0,它有著最為靈活的數據庫結構,對數據庫應用有著良好的支持。
論文主要介紹了本課題的開發背景,所要完成的功能和開發的過程。重點的說明了系統設計的重點、設計思想、難點技術和解決方案。
關鍵字:數據庫,SQL語言,Delph 6,數據庫組件,倉庫管理 目 錄
第一章 引言 ?????????????????????????????1 1.1 課題來源 ??????????????????????????1 1.2 開發工具的選擇 ???????????????????????2 1.3 所做的主要工作 ???????????????????????3 第二章 數據庫概論 ??????????????????????????4 2.1 數據庫的發展 ????????????????????????4 2.1.1 數據庫的發展 ??????????????????????4 2.1.2 數據庫階段的特點 ????????????????????5 2.1.3 數據庫技術 ???????????????????????6 2.2 數據庫理論基礎 ???????????????????????7 2.2.1 數據庫模型 ???????????????????????7 2.2.2 數據庫體系結構 ????????????????????10 2.2.3 數據的獨立性 ?????????????????????11 2.2.4 范式 ?????????????????????????11 2.3 SQL語言基礎 ???????????????????????13 2.3.1 SQL簡介 ???????????????????????13 2.3.2 SQL查詢 ???????????????????????13 2.3.3 SQL數據更新 ?????????????????????14 第三章數據庫開發工具 ???????????????????????16 3.1 Delphi 6.0 簡介 ???????????????????????16 3.2 Delphi 6.0 控件 ???????????????????????17 3.2.1 ADO數據訪問組件 ???????????????????17 3.2.2 數據控制類DataControl ?????????????????18 3.2.3 數據訪問類DataAccess ?????????????????18 3.2.4 SQL語言在Delphi中的應用 ???????????????19 3.3 Access 簡介 ????????????????????????21 第四章 系統總體設計 ????????????????????????23 4.1 系統需求分析 ???????????????????????23 4.2 系統概要設計 ???????????????????????25 4.2.1 系統結構設計 ?????????????????????25 4.2.2 數據庫設計 ??????????????????????27 4.2.2.1 ER圖設計 ????????????????????27 4.2.2.2 數據庫表格設計??????????????????29 4.3系統詳細設計????????????????????????34 第五章 系統應用程序設計 ??????????????????????37 5.1 系統窗體模塊組成??????????????????????37 5.2 數據模塊窗體設置??????????????????????38 5.3 主窗體功能模塊的實現????????????????????39 5.4 入庫、出庫窗體模塊的實現??????????????????43 5.5 查詢功能的實現???????????????????????51 5.6 系統登陸窗體模塊的實現???????????????????52 5.7 用戶管理功能的實現?????????????????????54 5.7.1 用戶管理主窗體 ????????????????????54 5.7.2 密碼修改窗體模塊的實現 ????????????????54 5.7.3 用戶注冊窗體模塊的實現 ????????????????55 5.7.4 用戶注銷窗體模塊的實現 ????????????????57 結束語 ???????????????????????????????59 致謝 ????????????????????????????????60 參考文獻 ??????????????????????????????61 第一章 引 言 §1.1 課題來源
隨著社會經濟的迅速發展和科學技術的全面進步,計算機事業的飛速發展,以計算機與通信技術為基礎的信息系統正處于蓬勃發展的時期。隨著經濟文化水平的顯著提高,人們對生活質量及工作環境的要求也越來越高。書籍做為人類的精神食糧,在現代社會中越來越受到重視,大量的書籍出現在市場上,人們有了各種各樣不同的選擇。與此同時,為了管理大量的圖書,圖書倉庫也大量的出現,倉庫的管理問題也就提上了日程。隨著圖書的大量增加,其管理難度也越來越大,如何優化倉庫的日常管理也就成為了一個大眾化的課題。
在計算機飛速發展的今天,將計算機這一信息處理利器應用于倉庫的日常管理已是勢必所然,而且這也將為倉庫管理帶來前所未有的改變,它可以帶來意想不到的效益,同時也會為企業的飛速發展提供無限潛力。采用計算機管理信息系統已成為倉庫管理科學化和現代化的重要標志,它給企業管理來了明顯的經濟效益和社會效益。主要體現在:
極大提高了倉庫工作人員的工作效率,大大減少了以往入出存流程繁瑣,雜亂,周期長的弊端。基于倉庫管理的全面自動化,可以減少入庫管理、出庫管理及庫存管理中的漏洞,可以節約不少管理開支,增加企業收入。
倉庫的管理的操作自動化和信息的電子化,全面提高了倉庫的管理水平。
隨著我國改革開放的不斷深入,經濟飛速的發展,企業要想生存、發展,要想在激烈的市場競爭中立于不敗之地,沒有現代化的管理是萬萬不行的,倉庫管理的全面自動化、信息化則是其中極其重要的部分。為了加快倉庫管理自動化的步伐,提高倉庫的管理業務處理效率,建立倉庫管理系統已變得十分心要。
入庫、庫存、出庫還是現在企業圖書倉庫管理的常規基本模式,雖然,最近又出現了很多新的管理模式,如:基于零庫存思想的沃爾瑪特管理方式,但這些新的思想在中國大部分企業的管理中還是難以實現的。所以如何設計好倉庫管理系統,盡可能地減少倉庫管理的重復性和低效性就成為當前最為重要的問題。圖書倉庫管理的核心是入庫、庫存和出庫之間的聯系,如何處理好三者之間的關系是系統最為關鍵的部分。另外,員工信息和供應商信息管理也是倉庫管理中一個必不可少的部分,它提供著與入庫和出庫相關的地一些信息,使得整個系統更加完整,更加實用。通過對倉庫管理日常工作的詳細調查,搜集了大量的資料,從系統結構的組織,功能的實現,技術的要求以及可行性等多方面進行考慮,認為本課題是一個適應現今圖書倉庫管理需求的計算機信息管理系統,具有一定的實際開發價值和使用價值。§1.2 開發工具的選擇
自Java誕生以來,隨著Internet技術的普及和應用需求的變化,以第四代語言為主的應用開發產品發生了較大的變化,它們不僅已成為人們開發應用的開發工具,而且很多產品已發展成為一種強有力的應用開發環境。這些新型的開發工具通常以一種集成軟件包的形式提供給開發人員,被稱為Studio(工作室)或Suite(程序組)。例如,微軟的Visual Studio 6.0,Borland公司的Delphi 6.0等數據庫輔助開發工具。
現在,市場上可以選購的應用開發產品很多,流行的也有數十種。目前在我國市場上最為流行、使用最多、最為先進的可用作企業級開發工具的產品有: Microsoft公司的Visual Basic 6.0版 Microsoft公司的Visual C++6.0版 Borland公司的Delphi 6.0版
在目前市場上這些眾多的程序開發工具中,有些強調程語言的彈性與執行效率;有些則偏重于可視化程序開發工具所帶來的便利性與效率的得高,各有各的優點和特色,也滿足了不同用戶的需求。然而,語言的彈性和工具的便利性是密不可分的,只有便利的工具,卻沒有彈性的語言作支持,許多特殊化的處理動作必需要耗費數倍的工夫來處理,使得原來所標榜的效率提高的優點失去了作用;相反,如果只強調程語言的彈性,卻沒有便利的工具作配合,會使一些即使非常簡單的界面處理動作,也會嚴重地浪費程序設計師的寶貴時間。
而Delphi是一個非常理想選擇。Delphi 6 是操作系統中快速應用開發環境的最新版本。它也是當前Windows平臺上第一個全面支持最新Web服務的快速開發工具。無論是企業級用戶,還是個人開發者,都能夠利用Delphi 6 輕松、快捷地構建新一代電子商務應用。Delphi 6 是惟一支持所有新出現的工業標準的RAD環境,包括XML(擴展標記語言)/XSL(可擴展樣式語言),SOAP(簡單對象存取協議)和WSDL(Web服務器描述語言)等。Delphi 6 是可視化的快速應用程序開發語言,它提供了可視化的集成開發環境,這一環境為應用程序設計人員提供了一系列靈活而先進的工具,可以廣泛地用于種類應用程序設計。在Delphi 6 的集成開發環境中,用戶可以設計程序代碼、運行程序、進行程序錯誤的調試等,可視化的開發方法降低了應用程序開發的難度。Delphi的基礎編程語言是具有面向對象特性的Pascal語言,即Object Pascal。Object Pascal具有代碼穩定、可讀性好、編譯速度快等優點,并將面向對象的概念移植到了Pascal語言中,使這種基礎語言有了新的發展空間。
使用Delphi 6.0,我們幾乎可以作任何事情,還可以撰寫種各種類型的應用程序,動態鏈接庫(DLL)、CON、或CORBA對象,CGI/ISAPI程序,Microsoft Back Office應用程序。程序的規模小到簡單的個人數據庫應用,大到復雜的企業的多層次分布式系統,都可以使用Delphi進行開發,其友好的集成開發界面,可視化的雙向開發模式,良好的數據庫應用支持高效的程序開發和程序運行,備受廣大程序開發人員的好評。尤其是Delphi對數據庫應用的強大支持,大大提高了數據庫應用軟件開發的效率,縮短了開發周期,深受廣大數據庫應用程序設計人員的喜愛。Delphi為數據庫應用開發人員提供了豐富的數據庫開發組件,使數據庫應用開發功能更強大,控制更靈活,編譯后的程序運行速度更快。§1.3 本文所做工作
引言部分介紹了本系統的課題來源以及對數據庫開發工具的選擇。
第二章介紹了數據庫的發展,關系數據庫,數據庫體系結構,并系統介紹了SQL語言,為設計和理解應用程序做了鋪墊。
第三章系統介紹了Delphi 6.0及其部分控件,SQL語言在Delphi 6.0中的應用,以及Access等。
第四章是本文的主體,按照軟件工程的要求,從需求分析開始,經過概要設計最后到詳細設計,完成對整個系統的設計。
第五章根據第四章的設計結果利用Access 2000和Delphi 6.0進行了具體的窗體和應用程序設計。
總結部分介紹了設計體會和編程體會,并指出了系統設計中的不足和改進的方向 第二章 數據庫概論 §2.1 數據庫的發展
數據庫處理在信息系統的研究中一直是非常重要的主題,然而,近年來,隨著World Wide Web(www.tmdps.cn公司的TOTAL等
(3)關系模型。關系模型的主要是用二維表格結構表達實體集,用外鍵表示實體間聯系。關系模型是由若干個關系模式組成的集合。關系模式相當于前面提到的記錄類型,它的實例稱為關系,每個關系實際上是一張二維表格。
關系模型和層次、網狀模型的最大判別是用關鍵碼而不是用指針導航數據,表格簡單用戶易懂,編程時并不涉及存儲結構,訪問技術等細節。關系模型是數學化模型。SQL語言是關系數據庫的標準化語言,已得到了廣泛的應用。20世紀70年代對關系數據庫的研究主要集中在理論和實驗系統的開發方面。80年代初才形成產品,但很快得到廣泛的應用和普及,并最終取代了層次、網狀數據庫產品。現在市場上典型的關系DBMS產品有DB2、ORACLE、SYBASE、INFORMIX和微機型產品Foxpro、Access等。
關系模型和網狀、層次模型的最大區別是:關系模型用表格數據而不是通過指針鏈來表示和實現實體間聯系。關系模型的數據結構簡單、易懂。只需用簡單的查詢語句就可對數據庫進行操作。關系模型是數學化的模型,可把表格看成一個集合,因此集合論、數理邏輯等知識可引入到關系模型中來。關系模型已是一個成熟的有前途的模型,已得到廣泛應用。
(4)面向對象模型。目前,關系數據庫的使用已相當普遍,但是,現實世界中仍然存在著許多含有復雜數據結構的應用領域,例如,CAD數據、圖形數據等,而關系模型在這方面的處理能力就顯得力不從心。因此,人們需要更高級的數據庫技術來表達這類信息。面向對象的概念最早出現在程序設計語言中,隨后迅速滲透到計算機領域的每一個分支。面向對象數據庫是面向對象概念與數據庫技術相結合的產物。
面向對象模型能完整地描述現實世界的數據結構,具有豐富的表達能力,但模型相對較復雜,涉及的知識面也廣,因此面向對象數據庫尚未達到關系數據庫那樣的普及程度。
2.2.2 數據庫體系結構
數據庫的體系結構分三級:內部級(internal),概念級(conceptual)和外部級(external)。這個三級結構有時也稱為“三級模式結構”,或“數據抽象的三個級別”,最早是在1971年通過的DBTG報告中提出,后來收入在1975年的美國ANSI/SPARC報告中。雖然現在DBMS的產品多種多樣,在不同的操作系統支持下工作,但是大多數系統在總的體系結構上都具有三級模式的結構特征。從某個角度看到的數據特性稱為“數據視圖”(data view)。
外部級最接近用戶,是單個用戶所能看到的數據特性。單個用戶使用的數據視圖的描述稱為“外模式”。
概念級涉及到所有用戶的數據定義,是全局的數據視圖。全局數據視圖的描述稱為“概念模式”。內部級最接近于物理存儲設備,涉及到實際數據存儲的結構。物理存儲數據視圖的描述稱為“內模式”。
數據庫的三級模式結構是數據的三個抽象級別。它把數據的具體組織留給DBMS去做,用戶只要抽象地處理數據,而不必關心數據在計算機中的表示和存儲,這樣就減輕了用戶使用系統的負擔。三級結構之間往往差別很大,為了實現這三個抽象級別的聯系和轉換,DBMS在三級結構之間提供兩個層次的映象(mappings):外模式/模式映象,模式/內模式映象。此處模式是概念模式的簡稱。
2.2.3 數據的獨立性
由于數據庫系統采用三級模式結構,因此系統具有數據獨立性的特點。在數據庫技術中,數據獨立性是指應用程序和數據之間相互獨立,不受影響。數據獨立性分成物理數據獨立性和邏輯數據獨立性兩級。(1)物理數據獨立性
如果數據庫的內模式要進行修改,即數據庫的存儲設備和存儲方法有所變化,那么模式/內模式映象也要進行相當的修改,使概念模式盡可能保持不變。也就是對內模式的修改盡量不影響概念模式,當然,對于外模式和應用程序的影響更小,這樣,我們稱數據庫達到了物理數據獨立性。(2)邏輯數據獨立性
如果數據庫的概念模式要進行修改,譬如增加記錄類型或增加數據項,那么外模式/模式映象也要進行相應的修改,使外模式盡可能保持不變。也就是對概念模式的修改盡量不影響外模式和應用程序,這樣,我們稱數據庫達到了邏輯數據獨立性。
現有關系系統產品均提供了較高的物理獨立性,而對邏輯獨立性的支持尚有欠缺,例如,對外模式的數據更新受到限制等。2.2.4 范式
建立起一個良好的數據指標體系,是建立數據結構和數據庫的最重要的一環。一個良好的數據指標體系是建立DB的必要條件,但不是充分條件。我們完全可以認為所建指標體系中的一個指標類就是關系數據庫中的一個基本表,而這個指標類下面的一個個具體指標就是這個基本表中的一個字段。但如果直接按照這種方式建庫顯然還不能算最佳。對于指標體系中數據的結構在建庫前還必須進行規范化的重新組織。
在數據的規范化表達中,一般將一組相互關聯的數據稱為一個關系(relation),而在這個關系下的每個數據指標項則被稱為數據元素(data element),這種關系落實到具體數據庫上就是基本表,而數據元素就是基本表中的一個字段(field)。規范化表達還規定在每一個基本表中必須定義一個數據元素為關鍵字(key),它可以唯一地標識出該表中其它相關的數據元素。在規范化理論中表是二維的,它有如下四個性質:
在表中的任意一列上,數據項應屬于同一個屬性(如圖中每一列都存放著不同合同記錄的同一屬性數據)。
表中所有行都是不相同的,不允許有重復組項出現(如圖中每一行都是一個不同的合同記錄)。在表中,行的順序無關緊要(如圖中每行存的都是合同記錄,至于先放哪一個合同都沒關系)。在表中,列的順序無關緊要,但不能重復(如圖中合同號和合同名誰先誰后都沒關系,但二者不可重復或同名)。
在對表的形式進行了規范化定義后,數據結構還有五種規范化定義,定名為規范化模式,稱為范式。在這五種范式中,一般只用前三種,對于常用系統就足夠了。而且這五種范式是“向上兼容”的,即滿足第五范式的數據結構自動滿足一、二、三、四范式,滿足第四范式的數據結構自動滿足第一、二、三范式,??,依此類推。
第一范式(first normal form,簡稱1st NF)就是指在同一表中沒有重復項出現,如果有則應將重復項去掉。這個去掉重復項的過程就稱之為規范化處理。在本文所討論的開發方法里,1st NF實際上是沒有什么意義的。因為我們按規范化建立的指標體系和表的過程都自動保證了所有表都滿足1st NF。
第二范式(second normal form,簡稱 2nd NF)是指每個表必須有一個(而且僅一個)數據元素為主關鍵字(primary key),其它數據元素與主關鍵字一一對應。例如,在圖l9.7中如果我們將合同號定義為主關鍵字(其它數據元素中的記錄數據都有可能重名,故不能作為主關鍵字),故只要知道了一個合同記錄的合同號,就可以唯一地在同一行中找到該合同的任何一項具體信息。通常我們稱這種關系為函數依賴(functional depEndence)關系。即表中其它數據元素都依賴于主關鍵字,或稱該數據元素唯一地被主關鍵字所標識。
第三范式(third normal form,簡稱 3rd NF)就是指表中的所有數據元素不但要能夠唯一地被主關鍵字所標識,而且它們之間還必須相互獨立,不存在其它的函數關系。也就是說對于一個滿足了 2nd NF的數據結構來說,表中有可能存在某些數據元素依賴于其它非關鍵宇數據元素的現象,必須加以消除。
為防止數據庫出現更新異常、插入異常、刪除異常、數據冗余太大等現象,關系型數據庫要盡量按關系規范化要求進行數據庫設計。
§2.3 SQL語言基礎 2.3.1 SQL簡介
用戶對數據庫的使用,是通過數據庫管理系統提供的語言來實現的。不同的數據庫管理系統提供不同的數據庫語言。關系數據庫管理系統幾乎都提供關系數據庫標準語言——SQL。
SQL 的全稱是Structured Query Language,即結構化查詢語言。SQL語句可以從關系數據庫中獲得數據,也可以建立數據庫、增加數據、修改數據。1986年ANSI采用SQL語言作為關系數據庫系統的標準語言,后被國際化標準組織(ISO)采納為國際標準。SQL語言使用方便、功能豐富、簡潔易學,是操作數據庫的工業標準語言,得到廣泛地應用。例如關系數據庫產品DB2、ORACLE等都實現了SQL語言。同時,其它數據庫產品廠家也紛紛推出各自的支持SQL的軟件或者與SQL的接口軟件。這樣SQL語言很快被整個計算機界認可。
SQL語言是一種非過程化語言,它一次處理一個記錄集合,對數據提供自動導航。SQL語言允許用戶在高層的數據結構上工作,而不對單個記錄進行操作。SQL語言不要求用戶指定數據的存取方法,而是使用查詢優化器,由系統決定對指定數據存取的最快速手段。當設計者在關系表上定義了索引時,系統會自動利用索引進行快速檢索,用戶不需知道表上是否有索引或者有什么類型的索引等細節。
SQL語言可以完成許多功能,例如: ● 查詢數據
● 在數據庫表格中插入、修改和刪除記錄 ● 建立、修改和刪除數據對象 ● 控制對數據和數據對象的存取 ● 確保數據庫的一致性和完整性等 2.3.2 SQL查詢
數據查詢是關系運算理論在SQL語言中的主要體現,SELECT 語句是SQL查詢的基本語句,當我們在對一個數據庫進各種各樣的操作時,使用的最多的就是數據查詢,在以SQL為基礎的關系數據庫中,使用的最多的就是SELECT查詢語句。SELECT語句的完整句法如下: SELECT 目標表的列名或列表達式序列 FROM 基本表和(或)視圖序列 [WHERE 行條件表達式] [GROUP BY 列名序列] [HAVING 組條件表達式] [ORDER BY列名 [ASC│DEAC]?]
我在SELECT語句中還使用了大量的保留字和通配符以進行各種各樣的條件查詢。在系統中有大量的查詢按鈕,其使用了大量的查詢語句,而且這些查詢語句大部分使用的是模糊查詢,所以大量的使用了模式匹配符LIKE(判斷值是否與指定的字符通配格式相符)。在包含LIKE的查詢語句中可以使用兩個通配符:%(百分號):與零個或多個字符組成的字符串匹配;_(下劃線):與單個字符匹配。系統中的條件判斷往往包含多個條件,這時就需要使用邏輯運算符NOT、AND、OR(用于多條件的邏輯連接),謂詞ALL以及保留字DISTINCT等等。做為SELECT語句還有很多的使用方法,這里就不再敘述。2.3.3 SQL數據更新
使用數據庫的目的是為了有效地管理數據,而數據的插入、刪除和修改則是必不可少的一個功能。在本系統中就大量地使用了數據插入、刪除和修改這三種操作,現做一個簡單地介紹。●數據插入
往數據庫的基本表中插入數據使用的是INSERT語句,其方式有兩種:一種是元組值的插入,另一種是查詢結果的插入。在本系統中使用的是前一種方式,其句法如下: INSERT INTO 基本表名(列表名)VALUES(元組值)●數據刪除
往數據庫的基本表中刪除數據使用的是DELETE語句,其句法如下: DELETE FROM 基本表名 [WHERE 條件表達式] 在些作一點說明,刪除語句實際上是“SELECT * FROM 基本表名 [WHERE 條件表達式]”和DELETE操作的結合,每找到一個元組,就把它刪除。此外,DELETE語句只能從一個基本表中刪除元組,WHERE子句中條件可以嵌套,也可以是來自幾個基本表的復合條件。●數據修改
當需要修改基本表中元組的某些列值時,可以用UPDATE語句實現,其句法如下: UPDATE基本表名
SET列名=值表達式[,列名=值表達式?] [WHERE條件表達式] 在Delphi中使用SQL語句是很方便的,一般來說,都是通過TQuery組件來使用SQL語言的。有一點要進行說明,雖然通過TQuery組件來使用SQL語言很方便,但考慮到自己對不同組件的理解程度、個人習慣以及其它各個方面,在本系統中我采用的是ADO組件來對數據庫進行操作。最簡單的方法比如在TADOQuery組件的SQL屬性中就可以鍵入SQL語句,至于詳細的使用方法在后面進行介紹。
第三章 數據庫開發工具 §3.1 Delphi 6.0 簡介
Delphi類可以粗略地分成兩部分:一部分是組件類,這些組件類通常以某種方式出現在組件面板上,當用戶從組件面板上點取一個類的圖標后,在程序中就自動生成了該類的對象(非可視組件除外);另一部分是功能類,這此功能類的對象通常出現在程序代碼中,起著不可代替的作用,但是這些功能類在組件面板上是找不到的。在Delphi中,每一個類的祖先都是Tobject類,整個類的層次結構就像一棵倒掛的樹,在最頂層的樹根即為Tobject類。這樣,按照面向對象編程的基本思想,就使得用戶可用Tobject類這個類型代替任何其它類的數據類型。實際上在Delphi的類庫中,Tobject類派生出了為數相當眾多的子類,它們形成了一個龐大的體系,通常情況下,如果不自行開發組件,就不必了解整個類的體系結構,只用到類層次樹的葉結點就足夠了。凡是做過程序開發的人都知道從來沒有單純的數據應用程序,也就是說,數據庫應用程序必須和用戶界面(可以是圖形界面,也可以是命令接口)元素相結合,只講界面或只講數據庫本身都構不成數據庫應用程序,因而用Delphi 6.0開發數據庫應用程序就隱含著界面開發。Delphi6中的VCL組件可用圖3-1來說明。組件在Delphi程序的開發中是最顯眼的角色。大家知道,在編寫程序時一般都開始于在組件面板上選擇組件并定義組件間的相互作用。但也有一些組件不在組件面板上,例如Tform和Tapplication(典型的非可視組件)。組件是Tcomponents派生出來的子類,可以流的形式存放在DFM文件中,具有事件和Publish屬性。
窗口組件類是窗口化的可視化組件類,在Delphi的類庫中占有最大的份額。在實際編程中,窗口組件類的對象都有句柄,可以接受輸入焦點和包含其它組件。
圖形組件與窗口組件并列,是另一大類組件。圖形組件不是基于窗口的,因而不能有窗口句柄,不能接受輸入焦點和包含其它組件。從圖8-43中可以看出,圖形組件的基類是TgraphicControl,在實際編程中,它們必須寄生于它們的宿主——窗口組件類的對象,由它們的擁有者負責其顯示,而且它們還能觸發一些和鼠標活動相關的事件。圖形控件最典型的例子是Tlabel和TspeedButton。由此可以看出圖形組件的功能很弱,有讀者會問圖形組件的用處何在呢?其實使用圖形組件的最大好處在于節省資源,正是因為它們的功能較弱,所以使用的系統資源就要少。在一個應用程序中,如果能在不影響其功能的前提下合理大量地使用圖形組件,將會大減少程序對系統資源的消耗。
非可視組件是與可視組件相并列的另一類組件,非可視組件在程序運行中是不可見的(除各種對話框組件之外,事實上有人認為對話框組件不能歸入非可視組件,應該是另一種介于可視與非可視之間的組件)。§3.2 Delphi 6.0 控件
用Delphi6開發數據庫應用,重點是和各種數據庫組件打交道,當然也要使用其它的一些組件,現在就我在系統設計中所使用的重要組件給與簡單介紹。3.2.1 ADO數據訪問組件
ADO數據對象(Active Data Objects)實際是一種提供訪問各種數據類型的鏈接機制。ADO設計為一種極簡單的格式,通過ODBC的方法同數據庫接口中,可以使用任何一種ODBC數據源,即不止適合于SQL Server、Oracle、Access等數據庫應用程序,也適合于Excel表格、文本文件、圖形文件和無格式的數據文件。ADO是基于OLE-DB之上的技術,因此ADO通過其內部的屬性和方法提供統一的數據訪問接口方法。ADO使您的客戶端應用程序能夠通過OLE DB提供訪問和操作在數據庫服務器中的數據。ADO支持用于建立C/S和Web的應用程序的主要功能。其主要優點是易于使用、高速度、低內存支出和占用磁盤空間較少。ADO同時具有遠程數據服務(RDS)功能,通過RDS可以在一次往返過程中實現將數據從服務器移動到客戶端應用程序和Web頁、在客戶端對數據進行處然后將更新結果返回服務器的操作。
Delphi 6.0繼續對Microsoft的ADO訪問能力的支持。這種能力是通過一組新組件實現的,這些組件是在企業版的ADO組件頁中,在組件面版的ADO頁上可以找到這些組件。利用在前面章節提到的TdataSet抽象類,ADO組件可以不通過BDE而直接實現ADO連接。這意味著只需要很少的代碼就可以實現該連接并且性能得到提高。
利用ADO數據訪問組件,可以只使用ADO結構與數據庫取得聯系并對其中的數據進行操作,而在這些過程中完全不需要使用BDE。大多數的ADO連接和數據集組件都是與基于BDE的連接和數據集組件相類似的。TADOConnection組件與基于BDE的應用程序中的Tdatabase組件類似。TADOTable與Ttable,TADOQuery與Tquery,以及TADOStoreProc和TstoredProc之間都具有這種類似的對應關系。使用這些ADO組件的方式與我們常使用的數據訪問組件(基于BDE)都有許多相同之處。TTADODataSet沒有直接的BDE對應組件,但它提供了許多與Ttable和Tquery相同的功能。同樣,TADOCommand也沒有相對應的BDE組件,它是在Delphi/ADO環境中完成特定功能的組件。Delphi 6.0通過ADO數據集訪問組件,可以不借助BDE數據引擎而是通過微軟的OLEDB來訪問更為廣泛的數據庫中的數據。ADO數據集訪問組件與常用的數據訪問組件是并列的關系。
在系統中我主要使用的是ADOTablet和ADOQuery兩個組件。3.2.2 數據控制類DataControl 數據控制類負責數據庫數據的顯示,并把用戶對數據的修改傳回。這里的絕大多數組件,如DBText, DBEdit, DBMemo, DBImage, DBListBox, DBComboBox, DBCheckBox, DBRadioGroup, DBLookupListBox, DBLookupCombox, DBCtrGrid的功能和對應的非數據感知組件相同,如TEdit框,TRadioGroups單選按鈕組等,只不過在顯示數據庫數據時要用而已。在系統中主要使用數據網格控件DBGrid和數據庫導航器控件DBNavigator。3.2.3 數據訪問類DataAccess 數據庫應用系統中數據訪問是一個首要問題,包括單用戶和 C/S系統,都必須聯系一些數據庫和數據表文件。Delphi 6 提供了專門用于數據訪問的基類控件。主要包括數據源控件DataSource、客戶數據集控件ClientDataSet、數據集提供器控件DataSetProvider等等。
Tdatabase:當一個基于BDE的數據庫應用程序需要一個永久數據庫連接時,需要定制向一個數據庫服務器的連接時,需要事務控制和特殊的數據庫別名時就得用到Tdatabase對象。特別是當連接到一個遠程的SQL數據庫服務器時,如果要利用BDE進行數據庫事務處理,那么,TDatabase對象的威力就體現出來了。在一個應用程序中為每一個數據庫連接顯示的聲明Tdatabase對象要根據需要而定,不是必需的。對一個數據庫連接,如果沒有顯示的聲明并實例化TDatabase對象,系統就會產生一個帶有默認屬性的TDatabase對象。
TdataSource對象用于在DataSet對象(包括Tquery,TstoredProc,Ttable等)和數據感知組件之間提供一個連接的紐帶,以便在窗體上顯示數據庫中的數據,在數據庫中導航定位與編輯數據集中的數據。如果一個DataSet對象中的數據想在數據感知組件中顯示和修改,它就必須和TdataSource對象相聯系。同樣,一個數據感知組件如果想和數據源相聯系以便顯示和操縱數據,就必須以TDataSource對象為中介。
用Delphi6作數據庫應用開發概括來說如下:先利用數據存取組件和實際的數據庫建立連接,并用Tsession對象和Tdatabase對象管理這些連接。然后以Tdatasource對象為中介,用數據感知組件向用戶顯示數據庫的內容并接受用戶的查詢和修改等操作。3.2.4 SQL語言在Delphi中的應用
在Delphi中使用SQL語言非常方便,一般來說,都是通過Tquery組件來使用SQL語言的。可以在TQuery組件的SQL屬性中設置SQL語句。設計程序時,在該組件的屬性對話框中選擇SQL屬性,單擊帶省略號的按鈕,就可以打開String List Editor對話框,然后我們就可以在對話框中添加SQL語句。還可以使用Delphi的SQL Builder來自動生成SQL語句,這樣可以避免手工編寫SQL而可能造成的語法錯誤。
靜態SQL語句在程序設計時便已固定下來,它不包含任何參數和變量。
動態SQL語句,也被稱作參數化的語句,在其中間包含著表示字段名或表名的參數,例如下面的語句是一條動態SQL語句:
Select * From Students Where StudentCode =: StudentCode;其中的變量StudentCode便是一個參數變量,它由一個冒號引導,在程序運行過程中,必須要為該參數賦值,該條SQL語句才能正確執行,每次運行應用程序時可以為該參數變量賦予不同的值。為參數賦值有三種方法:
①根據參數在SQL語句中出現的順序,設置TQuery部件的Params屬性值為參數賦值。②直接根據SQL語句中各參數的名字,調用ParamByName方法來為各參數賦值。
③將TQuery部件的DataSource屬性設置為另一個數據源,這樣將另一個數據源中與當前TQuery部件的SQL語句中的參數名相匹配的字段值賦給其對應的參數。利用這種方法也能實現所謂的連接查詢,創建主要—明細型數據庫應用。
在程序運行過程中,要想設置TQuery部件的SQL屬性,必須首先調用Close方法,關閉TQuery部件,然后再調用Clear方法清除SQL屬性中現存的SQL命令語句,最后再調用Add方法為SQL屬性設置新的SQL命令語句。例如: Query1.Close {關閉Query1)Query1.SQL.Clear {清除SQL屬性中的SQL命令語句} Query1.SQL.Add(?Select * From Students?);Query1.SQL.Add(? Where Name =“Lucy” ?);
在為TQuery部件設置SQL屬性時調用Close方法總是很安全的,如果TQuery部件已經被關閉了,調用Close方法時不會產生任何影響。在應用程序中為SQL屬性設置新的SQL 命令語句時,必須要調用Clear方法以清除SQL屬性中現存的SQL命令語句,如果不調用Clear方法,便調用Add方法向SQL屬性中設置SQL命令語句,那么新設置的SQL命令語句會追加在現存SQL命令語句后面,在程序運行時常常會出現出乎意料的查詢結果甚至程序無法運行下去。在這里要特別注意的,一般情況下TQuery部件的SQL屬性只能包含一條完整的SQL語句,它不允許被設置成多條SQL語句。當然有些數據庫服務器也支持在TQuery部件的SQL屬性中設置多條SQL語句,只要數據庫服務器允許這樣,我們在編程時可以為 SQL 屬性設置多條SQL語句。
在為TQuery部件設置完SQL屬性的屬性值之后,也即編寫好適當的SQL程序之后,可以有多種方式來執行SQL程序。
在設計過程中,設置完TQuery部件的SQL屬性之后將其Active屬性的值置為True,這樣便可以執行SQL屬性中的SQL程序,如果應用中有與TQuery部件相連的數據瀏覽部件(如TDDGrid TDBEdit等)那么在這些數據瀏覽部件中會顯示SQL程序的執行結果。
在應用程序運行過程中,通過程序調用TQuery部件的Open方法或ExecSQL 方法可以執行其SQL屬性中的SQL程序。Open方法和ExecSQL方法是不一樣的。Open方法只能用來執行SQL語言的查詢語句(Select命令),并返回一個查詢結果集,而ExecSQL方法還可以用來執行其它常用的SQL語句(如INSERT, UPDATE, DELETE等命令),例如: Query1.Open(這樣會返回一個查詢結果集)如果調用Open方法,而沒有查詢結果時,會出錯。此時應該調用ExecSQL 方法來代替Open方法。如:
Query1.ExecSQL(沒有返回結果)當然在設計應用程序時,程序設計人員是無法確定TQuery部件中的SQL 語句是否會返回一個查詢結果的。對于這種情況應當用Try…Except模塊來設計程序。在 Try 部分調用Open方法,而在Except部分調用ExceSQL方法,這樣才能保證程序的正確運行。
Delphi中用ADOQuery來使用SQL語句同樣十分方便。在ADOQuery組件中首先通過ConnectionString屬性值來聯接數據源,然后就通過雙擊SQL…屬性值來寫入SQL語句。在Delphi中調用數據庫,就可以調用ADOQuery組件,通過修改其中的SQL…屬性中的SQL語句來實現對數據庫的各項操作。
值得注意的是,ADOQuery組件只有在激活的情況下才可以被正確地使用,這樣就提出了一個問題,也就是說,在每次修改ADOQuery組件的SQL…屬性時都必須先行進行關閉,待清除掉SQL…中所有的SQL語句后才可以添加新的SQL語句。而且,在每一次修改完成以后,還應該記得重新將ADOQuery激活。其它的使用方法與TTQuery有許多的相似之處。§3.3 Access 簡介
建立一個數據庫我們有多種選擇,現在市場上有各種各樣的數據庫,而且每一種數據庫都有其自身的特點,不能說哪一種更好,只能在其中尋找一種能更好地適應系統需求、更好地滿足用戶的要求以及適應開發人員的習慣。在本系統中,做為圖書倉庫管理系統是一個比較小的應用系統,它所產生和處理的數據量也比較小。因此,沒有必要使用像SQL Server和Oracle這樣的大型數據庫。我首先想到的數據庫是Borland公司的Paradox數據庫。另外,Microsoft Office中的Access數據庫在計算機上的應用比較普及,是開發小型數據庫系統的比較理想的選擇,所以,在本系統中我選擇了Access數據庫。
Access做為一個數據庫管理系統,它被集成在Microsoft Office中。Access數據庫處理的基本結構,采取關系型數據庫模式。與其他的數據庫系統相比,Access更加簡單易學,一個普通的計算機用戶可以很快地掌握它。Access 2000的功能十分強大,利用它可以方便地實現對信息保存、維護、查詢、統計、打印、交流、發布,而且它可以十分方便地與Office其他組件交流數據,這些功能對一個一般用戶而言已經足夠了。第四章 系統總體設計
軟件系統的總體設計大約要經歷可行性分析和項目開發計劃,需求分析,概要設計,詳細設計,編碼,測試以及維護等七個階段。可行性分析和項目開發計劃在前面已經敘述,下面所要做的是進行軟件需求分析,概要設計和詳細設計。編碼過程將在下一節論述,而測試和維護過程不在本文敘及。
§4.1 系統需求分析
在經過前一階段的分析之后,我確定了我的開發課題為圖書倉庫管理。現在所要做的是要準確定義系統必須做什么以及系統必須具備的功能。
軟件需求分析中我采用結構化分析方法(Structured Analysis,簡稱SA),SA是面向數據流進行需求分析的方法,像所有的軟件分析方法(如面向對象分析方法、IDEF方法等等)一樣,SA也是一種建模活動,它使用簡單易讀的符號,根據軟件內部數據傳遞、變換的關系,自頂向下逐層分解,描繪滿足功能要求的軟件模型。
在系統中我采用數據流圖(DFD)這種半形式化的描述方式表達需求。它是一種功能模型,以圖形的方式描繪數據在系統中流動和處理的過程,只反映系統必須完成的邏輯功能。它有四種基本圖形符號:
◆ →:箭頭,表示數據流; ◆ 〇:圓或橢圓,表示加工; ◆ ═:雙杠,表示數據存儲;
◆ □:方框,表示數據的源點或終點。
為了表達較為復雜問題的數據處理過程,用一張數據流圖是不夠的,要按照問題的層次結構進行逐步分解,并以一套分層的數據流圖反映這種結構關系。在這里我一共使用了三層數據流圖,即頂層圖,0層圖和1層圖(也是底層圖)。
在多層數據流圖中,頂層流圖僅包含一個加工,它代表被開發系統,它的輸入流是該系統的輸入數據了,輸出流是該系統的輸出數據;底層流圖是指其加工不需要再做分解的數據流圖,中間層流圖表示對其上層父圖的細化,它的每一步加工可能繼續細化成子圖。經過對系統的分析首先得到系統的頂層DFD,如下: 一步細化得到系統的0層DFD,如下:
再進一步細化每一個數據加工功能,得到系統的1層DFD圖。
在這里只給出有關入庫管理和出庫管理的1層數據流圖,它們是系統的關鍵部分,也是主要的部分。通過以上對數據流圖的分析之后,我們已大體地了解了系統的功能和目標,接下來所要做的就是系統功能模塊的劃分和數據庫的設計,也就是系統的概要設計。§4.2 系統概要設計 在軟件需求分析階段,搞清楚了軟件“做什么”的問題,形成了目標系統的邏輯模型。現在我們所要做的就是要把軟件“做什么”的邏輯模型變換為“怎么做”的物理模型,即著手實現軟件的需求。首先,我們需要描述的是系統的總的體系結構。4.2.1 系統結構設計
系統的概要設計中最重要的就是系統的模塊化。模塊化是指解決一個復雜問題時自項向下逐層把軟件系統劃分成若干個模塊的過程。每個模塊完成一個特定的功能,所有的模塊按某種方法組織起來,成為一個整體,完成整個系統所要求的功能。
將系統劃分為多個模塊是為了降低軟件系統的復雜性,提高可讀性、可維護性,但模塊的劃分不能是任意的,應盡量保持其獨立性。也就是說,每個模塊只完成系統要求的獨立的子功能,并且與其他模塊的聯系最少且接口簡單,即盡量做到高內聚低耦合,提高模塊的獨立性,為設計高質量的軟件結構奠定基礎。
在系統的概要設計中我采用結構化設計(Structure Design,簡稱SD),SD以需求分析階段產生的數據流圖DFD為基礎,按一定的步驟映射成軟件結構。我首先將整個系統化分為幾個小問題,小模塊,在系統中,我設計了用戶管理、庫存管理、入庫管理、出庫管理、員工管理和供應商管理6個小模塊。然后,進一步細分模塊,添加細節。比如,用戶管理我又將其分為用戶注冊、用戶注銷、密碼修改;庫存管理分為庫存記錄查詢、庫存記錄修改、庫存記錄打印等等。以下就是系統的結構圖:(在這里為了表達方便我將結構圖分開來表達。)
在得到系統的第一層功能模塊圖后,經過進一步地細化,得一系統的子功能模塊圖: 4.2.2 數據庫設計
在信息世界中,信息從客觀事物出發流經數據庫,通過決策機構最后又回到客觀世界,信息的這一循環經歷了三個領域:信息世界,數據世界,現實世界。現實世界的事物反映到人的頭腦中,人的大腦對它有個認識過程,經過分析(選擇、命名、分類等)進入信息世界。這些信息再進一步加工、編碼,然后進數據世界,而軟件系統的開發工作需要考慮這兩個方面的問題,也就是要考慮系統開發所需要的數據,以及如何對這些數據進行操作。這兩個問題貫穿了整個軟件系統的開發過程,這也就是數據庫的設計問題,軟件設計的一個核心。4.2.2.1 ER圖設計
在系統設計的開始,我首先考慮的是如何用數據模型來數據庫的結構與語義,以對現實世界進行抽象。目前廣泛使用的數據模型可分為兩種類型,一種是獨立于計算機系統的“概念數據模型”,如“實體聯系模型”;另一種是直接面向數據庫邏輯結構的“結構數據模型”。在本系統中我采用“實體聯系模型”(ER模型)來描述數據庫的結構與語義,以對現實世界進行第一次抽象。ER模型直接從現實世界抽象出實體類型及實體間聯系,然后用ER圖來表示數據模型。它有兩個明顯的優點:接近于人的思維,容易理解;與計算機無關,用戶容易接受。但ER模型只能說明實體間語義的聯系,不能進一步說明詳細的數據結構,它只是數據庫設計的第一步。ER圖是直觀表示概念模型的工具,它有四個基本成分: ◆ 矩形框,表示實體類型(考慮問題的對象)。◆ 菱形框,表示聯系類型(實體間的聯系)。
◆ 橢圓形框,表示實體類型和聯系類型的屬性。對于關鍵碼的屬性,在屬性名下劃一橫線。◆直線,聯系類型與其涉及的實體類型之間以直線連接。
本系統為圖書倉庫管理,主要管理圖書的入庫、出庫以及庫存等事項。倉庫根據需要可以查詢圖書供應商的信息,同時還需要了解在入庫和出庫中員工的參與情況。依據倉庫管理的實際情況,考慮了多方面的因素以后,確定系統的ER圖如下:
(為了表達的方便,在這里我沒有在一張圖上表達出所有的關系,而是用一張總體ER圖,和幾張實體屬性關系圖來表達數據庫的結構。)
在該數據庫中,我設計了三個實體,分別是庫存、員工和供應商以及兩個聯系類型入庫和出庫。在本系統中庫存是核心,也是基本,沒有了庫存其它的也就沒有什么意義了。員工記錄的添加是考慮到責任問題,也就是說,在倉庫管理的實際運用中,出現了責任不清的現象,特別是由于倉庫的進出圖書數量都比較大時產生了一系列問題,所以在設計數據庫時,我特別考慮到這一點,加入了員工記錄這一實體。供應商信息的添加主要出于對圖書來源問題的思考。通過添加供應商信息可以比較清楚地了解圖書的進貨渠道,從圖書的質量到供應商的信譽都可以進行了解,同時可以為以后的圖書進購提供一定有用的信息。
入庫聯系類型將庫存信息、供應商信息和員工信息聯系在一起,可以方便地實現三個實體之間的聯接,而出庫聯系類型則將庫存信息和員工信息較好地聯接起,同時這兩個聯系類型又都具有各自特有的屬性。
下面就是各實體及聯系類型的屬性圖:(帶#號的屬性為關鍵字段)4.2.2.2 數據庫表格設計 在完成系統的ER圖之后,需要將ER模型轉化為關系模型,也就是說,要設計出數據庫所需要的表格。在這里,我選用的是關系數據庫。因為關系數據庫中的二維表格可以很清楚地描述數據之間的聯系。
在這里不得不提到一個概念——范式。其實在上一節的ER圖設計中,已經運用了范式的思想,不僅如此,在數據庫的表格設計中更離不開范式的思想,它是數據庫設計的基礎,如果不注意這個問題將會導致一系列問題的出現。
我在系統中定義的表格都嚴格地按照范式的思想和要求去完成,數據庫中的所有表格都達到了三范式的要求。根據系統ER圖,針對本系統的特點,在對所搜集的數據進行規范化之后,定義了如下六張表格,分別是庫存信息表,入庫信息表,出庫信息表,員工信息表,供應商信息表和密碼信息表。通過對這六張表格的操作可以較好地完成系統設計的各項功能,六張表格之間有著不同程度的聯系。(說明:在以下數據表中,K代表主鍵,#代表外鍵,字段值不為空。)BookRecord 表(庫存信息表)
字段名稱 數據類型 說明 K BookID 數字 圖書編號 BookName 文本 圖書名 Author 文本 作者 Publisher 文本 出版社 PubDate 日期/時間 出版日期 Price 貨幣 價格 BookType 文本 圖書類型 Number1 數字 庫存數量 Addation 文本 備注 圖4.13 庫存信息表
庫存信息表主要用于記錄倉庫中現存放的所有圖書的詳細信息,包括圖書編號、書名、作者、出版社、圖書類型等有關圖書的各類信息,它即是該數據庫的主表,也是系統主界面的主要內容。在該表中圖書編號是主鍵,它按圖書入庫的先后次序來編寫,每當有圖書入庫,系統自動給出圖書編號,這樣我們按圖書編號來查找圖書是比較方便的。考慮到編號比較難于記憶,所以使用了出版社和圖書類型兩個字段,在系統中我提供了出版社和圖書類型的分類查找,而且全部采用自動生成,每當系統中有新的出版社類型和圖書類型,彈出菜單會自動添中新類型,這樣就可以比較方便地實現按出版社和按圖書類型查找。此外,庫存數量也是一個比較關鍵的字段,該字段是在系統初始化時就給定的,每當有圖書入庫或出庫操作,系統就會自動修改圖書的庫存數量,以保持數據的一致性。做為備注有一點說明,我的數據庫中備注的數據類型是文本,而不是備注類型,主要考慮到該字段的長度并不大,而且在Delphi中文本數據類型的處理也比較方便一點。Employee 表(員工信息表)
字段名稱 數據類型 說明 K EmployeeID 數字 員工編號 EmployeeName 文本 員工姓名 Sex 文本 性別
BornDate 日期/時間 出生日期 Grade 文本 職稱
WorkDate 日期/時間 工作日期 Telephone 文本 聯系電話 Address 文本 聯系地址
圖4.14 員工信息表
員工信息表主要用于記錄有關員工的各類信息,包括姓名、職稱、出生日期、聯系電話、聯系地址等。它主要用來為系統提供員工的有關信息,因為在系統中,入庫和出庫操作均與員工有著一定的聯系,在查詢入庫信息和出庫信息時,有時需要查找有關此項記錄有關的員工信息,在系統中我是通過入庫記錄與員工記錄(出庫記錄和員工記錄)之間的聯接查詢來完成的。另外,作為一個倉庫也有必要了解其所屬員工的一些基本情況,以便查詢。Shopkeeper 表(供應商信息表)
字段名稱 數據類型 說明 K ShopkeeperID 數字 供應商編號 ShopkeeperName 文本 供應商姓名 Address 文本 地址 PostNo 數字 郵編
OfficePhone 文本 辦公電話 HomePhone 文本 住宅電話 Email 文本 E-mail PayType 文本 付款方式
圖4.15 供應商信息表
供應商信息表主要用于記錄有關供應商的各類信息,包括姓名、地址、電話、付款方式等。它主要用來為系統提供供應商的有關信息,在系統中入庫記錄是與供應商記錄相聯系的,通過入庫記錄可以查找相關的供應商信息。在供應商信息中,考慮當實際情況,我特別加入了Email和付款方式這兩個字段,因為在當今信息世界中,多種多樣的通訊方式和多種多樣的付款方式是必然的,是數據庫中必須與以記錄。
InRecord 表(入庫信息表)
字段名稱 數據類型 說明 K InID 數字 入庫編號 # BookID 數字 圖書編號 # EmployeeID 數字 員工編號 # ShopkeeperID 數字 供應商編號 Number 數字 入庫數量 BuyDate 日期/時間 入庫日期
圖4.16 入庫信息表
OutRecord 表(出庫信息表)
字段名稱 數據類型 說明 K OutID 數字 出庫編號 # BookID 數字 圖書編號 # EmployeeID 數字 員工編號 Number2 數字 出庫數量 OutDate 日期/時間 出庫日期 圖4.17 出庫信息表
入庫信息表主要用于記錄有關入庫的詳細信息,包括入庫數量、入庫日期以及圖書、員工、供應商三方的編號,以便查詢。出庫信息表主要用于記錄有關出庫的詳細信息,包括出庫數量、出庫日期以及圖書、員工的編號。出庫信息表和入庫信息表一樣,其實它們都屬于聯系類型,系統通過這兩個表可以聯接上其它的表為用戶提供多種條件的聯接查詢。值得提出的一點是入庫記錄和出庫記錄的添加不僅僅是單表操作,由于它們都與庫存記錄相聯系,所以,無論您是添中入庫記錄還是添加出庫記錄,都必須同時修改庫存記錄,以保持數據的一致性,否則將引發系統出錯而這些我都讓其在系統中自動完成。無論您是添加入庫記錄,還是添加出庫記錄,系統都將自動修改庫存中圖書的數量,而且,在您出庫的數量大于庫存數量時,系統還會自動提示錯誤,這樣就可以防止一定錯誤的發生。
在入庫信息表和出庫信息表中我還定義了幾個外鍵,它提供了一種表示幾個關系聯系的方法。比如,系統中通過在入庫信息表中定義的外鍵 BookID、EmployeeID和ShopkeeperID可以將庫存信息表、員工信息表和供應商信息表聯系在一起,從而方便地實現聯接查詢,而且,引入外鍵的定義是實體完整性約束的一個主要方面。Key 表(密碼信息表)
字段名稱 數據類型 說明 K KeyName 文本 用戶姓名 KeyNo 文本 用戶密碼 圖4.18 密碼信息表
密碼信息表主要用于記錄所有的用戶名和用戶密碼。它是在用戶登陸時用來確定用戶和密碼的正確性,以防止非法用戶登陸。通過以上設計已經完成了系統的概要設計,當我們有了系統的功能模塊圖和數據庫之后,就需要著手去實現每一個模塊,為每一個功能設計程序流程圖,這也就是系統的詳細設計。§4.3 系統詳細設計
在前面的概要設計中,已將系統劃分為多個模塊,并將它們按照一定的原則組裝起來,同時確定了每個功能及模塊之間的外部接口。現在所要做的就是確定每個模塊具體執行過程,也可以說是“過程設計”。
在處理過程設計時我采用的是結構化程序設計(簡稱SP)方法。需要指出的是系統的詳細設計并不是指具體的編程序,而是將概要設計階段產生的系統功能模塊圖細化成很容易產生程序的圖紙。因此詳細設計的結果基本決定了最終程序的質量。為軟件的質量,延長軟件的生存期,軟件的可測試性、可維護性提供重要的保障。詳細設計的目標不僅是邏輯上正確地實現每個模塊的功能,還應使設計出的處理過程清晰易讀。
由前一階段產生的系統功能模塊圖,我為系統的主要部分設計了如下程序流程圖:通過以上步驟,基本上完成了對整個系統的總體設計,接下來所要做的就是軟件的編碼工作。系統總體設計的好壞直接影響著下一步工作,只有在這一階段設計出好的模塊圖和程序流程圖,才能更有利于編碼,產生好的軟件系統。
第五章
系統應用程序設計 §5.1 系統窗體模塊組成 §5.2 數據模塊窗體的設置
在編寫數據庫應用程序時,經常要遇到這樣的情況,即好多組件、窗體同時訪問相同的數據源,如果為每一個組件或者窗體都設置一個數據源將是十分耗時的工件,而且要保證這些數據源的確是相同的也需花一番功夫。那么,能不能將這些數據源集中管理,最好是做成一個統一的模塊,需要時就將該模塊引入而不必直接操作數據源本身呢?數據模塊(DataModule)是解決這個問題最好的答案。簡單說來,數據模塊是用來集中管理數據源的一個窗體,該窗體可被需要的地方隨時引入。
圖5.2給出了本程序的數據模塊(datamoduleform)窗體圖,除報表窗體外所有的數據存取組件和數據源組件都在此數據模塊中進行了定義。值得一提的是,設置了數據庫Database組件,該組件引入了系統所需的唯一的數據庫tsxs,Database組件的DatabaseName屬性設置為tsckgl。tsxs數據庫已在ODBC配置程序中進行了設置。其他的數據存取組件都是基于此數據庫組件創建的,這樣做的好處是,當數據庫的別名或者其他信息改變之后,只需修改Tdatabase組件的AliasName屬性即可。
另外,在本系統的數據模塊窗體圖中,我大多采用的AODQuery組件而沒有采用BDE組,這主要是基于對ADO組件的了解。在Delphi的學習中我對ADO組件了解的更加清楚,使用也較BDE更為熟練,而且,ADO組件的功能也較BDE更為強大,所以在這里大多采用ADO組件來進行數據庫聯接。同時我也使用了BDE組件中的Table,因為在某些時候BDE有著其自身特有的優越性。主窗體功能模塊的實現 file://主窗體程序代碼
public
file://在程序的起始部分,定義快捷按鈕點擊事件 Procedure Popup1Handler(Sender:Tobject);Procedure Popup2Handler(Sender:TObject);********************************************************************** procedure Tmainform.Popup1Handler(Sender: TObject);begin file://快捷按鈕1(點“按出版社分類”按鈕產生)的點擊事件 with datamoduleform.MainQuery do
begin
file://打開數據模塊窗體的MainQuery,對BookRecord表進行操作 close;
file://關閉MainQuery SQL.Clear;
file://清除SQL屬性中的SQL命令語句
SQL.Add(?select * from BookRecord where Publisher=:Pub?);file://添加新的SQL語句 Parameters.ParamByName(?Pub?).Value:=(Sender as TMenuItem).Caption;open;
file://重新打開MainQuery end;end;********************************************************************** procedure Tmainform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3,s4,s5 :String;
file://設立5個變量以方便實現模糊查詢 begin
file://主窗口庫存查詢按鈕事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(?select * from BookRecord?);
SQL.Add(?where BookID Like :BookID and BookName Like :Name and Author Like :Author and Publisher Like :pub and BookType Like :BookType?);
file://使用Like語句來實現模糊查詢
if Edit1.Text<>?? then s1:=?%?+Edit1.Text+?%? else s1:=?%?;
Parameters.ParamByName(?BookID?).Value:=s1;
file://給變量s1賦值 if Edit2.Text<>?? then s2:=?%?+Edit2.Text+?%? else s2:=?%?;
Parameters.ParamByName(?Name?).Value:=s2;
file://給變量s2賦值 if Edit3.Text<>?? then s3:=?%?+Edit3.Text+?%? else s3:=?%?;
Parameters.ParamByName(?Author?).Value:=s3;
file://給變量s2賦值 if Edit4.Text<>?? then s4:=?%?+Edit4.Text+?%? else s4:=?%?;
Parameters.ParamByName(?Pub?).Value:=s4;
file://給變量s2賦值 if Edit5.Text <>?? then s5:=?%?+Edit5.Text+?%? else s5:=?%?;
Parameters.ParamByName(?BookType?).Value:=s5;
file://給變量s2賦值 open;if FieldValues[?BookID?]=NULL
file://判斷是否找到記錄 then begin Messagedlg(?沒有找到你所需要的記錄!?,mtInformation,[mbOK],0);Edit1.Text:=??;Edit2.Text:=??;Edit3.Text:=??;Edit4.Text:=??;Edit5.Text:=??;close;SQL.Clear;SQL.Add(?select * from BookRecord?);
file://這里相當于一個刷新功能 open;end;end;end;********************************************************************** procedure Tmainform.SpeedButton3Click(Sender: TObject);begin
file://庫存表刷新按鈕事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(?select * from BookRecord?);open;end;end;********************************************************************** procedure Tmainform.SpeedButton11Click(Sender: TObject);var PopupItem:TMenuItem;begin
file://自動生成快捷按鈕1的內容 with datamoduleform.BookQuery do begin
file://從數據庫中選擇出版社類型 close;SQL.Clear;SQL.Add(?select distinct Publisher from BookRecord?);open;PopupMenu1:=TPopupMenu.Create(Self);file://自動生成快捷菜單 PopupMenu1.AutoHotkeys:=maManual;file://自定義熱鍵 while Not Eof do begin
file://根據出版社內容生成菜單子項 PopupItem:=TMenuItem.Create(Self);PopupItem.Caption:=FieldByName(?Publisher?).AsString;PopupMenu1.Items.Add(PopupItem);PopupItem.onClick:=Popup1Handler;
file://確定菜單子項的點擊事件 Next;end;end;PopupMenu1.Popup(384,67);
file://在指定位置顯示快捷菜單1 end;********************************************************************** procedure Tmainform.FormActivate(Sender: TObject);begin
file://系統初始化,在進入mainform時自動添加數據源 mainform.DBGrid1.DataSource:=datamoduleform.MainSource;mainform.DBNavigator1.DataSource:=datamoduleform.MainSource;mainform.DBGrid2.DataSource:=datamoduleform.EmpSource;mainform.DBNavigator2.DataSource:=datamoduleform.EmpSource;mainform.DBGrid3.DataSource:=datamoduleform.ShopSource;mainform.DBNavigator3.DataSource:=datamoduleform.ShopSource;mainform.DBGrid4.DataSource:=datamoduleform.InSource;mainform.DBNavigator4.DataSource:=datamoduleform.InSource;mainform.DBGrid5.DataSource:=datamoduleform.OutSource;mainform.DBNavigator5.DataSource:=datamoduleform.OutSource;end;********************************************************************** procedure Tmainform.FormCreate(Sender: TObject);begin
file://系統初始化,定義界面大小,以適應不同分辯率 Width:=800;Height:=600;end;********************************************************************** procedure Tmainform.Timer1Timer(Sender: TObject);begin
file://在狀態欄顯示時間
StatusBar1.Panels[2].Text:=DateToStr(Date);StatusBar1.Panels[4].Text:=TimeToStr(Time);end;§5.4 入庫、出庫窗體模塊的實現
圖5.4 系統入庫管理窗體
圖5.5 系統出庫管理窗體
procedure Tinoutform.SpeedButton4Click(Sender: TObject);begin
file://入庫管理查找按鈕事件
with datamoduleform.BookQuery do file://入庫查詢處理
begin
close;
SQL.Clear;
SQL.Add(?select * from BookRecord where BookID=:BookID?);
Parameters.ParamByName(?BookID?).Value:=Edit13.Text;
open;
if FieldValues[?BookID?]<>NULL then begin
Edit1.Text:=??;
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;
Edit6.Text:=FieldValues[?BookName?];file://顯示圖書名
Edit6.ReadOnly:=true;Edit6.Color:=clMenu;file://設置顯示框不可更改屬性
Edit7.Text:=FieldValues[?Author?];
Edit7.ReadOnly:=true;Edit7.Color:=clMenu;
Edit8.Text:=FieldValues[?Publisher?];
Edit8.ReadOnly:=true;Edit8.Color:=clMenu;
Edit9.Text:=FieldValues[?PubDate?];
Edit9.ReadOnly:=true;Edit9.Color:=clMenu;
Edit10.Text:=FieldValues[?Price?];
Edit10.ReadOnly:=true;Edit10.Color:=clMenu;
Edit11.Text:=FieldValues[?BookType?];
Edit11.ReadOnly:=true;Edit11.Color:=clMenu;
Edit12.Text:=FieldValues[?Number1?];
Edit12.ReadOnly:=true;Edit12.Color:=clMenu;
If FieldValues[?Addation?]<>NULL then Edit25.Text:=FieldValues[?Addation?]
else Edit25.Text:=??;
Edit25.ReadOnly:=true;Edit25.Color:=clMenu;
end
else
begin file://在沒有查找到的情況下,清空所有顯示框
Edit1.ReadOnly:=false;Edit1.Text:=??;Edit1.Color:=clMenu;
Edit6.ReadOnly:=false;Edit6.Text:=??;Edit6.Color:=clMenu;
Edit7.ReadOnly:=false;Edit7.Text:=??;Edit7.Color:=clMenu;
Edit8.ReadOnly:=false;Edit8.Text:=??;Edit8.Color:=clMenu;
Edit9.ReadOnly:=false;Edit9.Text:=??;Edit9.Color:=clMenu;
Edit10.ReadOnly:=false;Edit10.Text:=??;Edit10.Color:=clMenu;
Edit11.ReadOnly:=false;Edit11.Text:=??;Edit11.Color:=clMenu;
Edit12.ReadOnly:=false;Edit12.Text:=??;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=??;Edit25.Color:=clMenu;
MessageDlg(?沒有找到你所需要的記錄!?,mtInformation,[mbOK],0);
Edit13.Text:=??;Edit13.SetFocus;
end;end;with datamoduleform.InQuery do file://自動入庫編號的獲取
begin
close;
SQL.Clear;
SQL.Add(?select * from InRecord where InID>=All(select InID from InRecord)?);
open;
file://找到入庫編號中最大的一個
Edit26.ReadOnly:=false;
Edit26.Text:=FieldValues[?InID?]+1;file://最大的入庫編號加1形成新的入庫編號
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;file://設置編號的不可更改性
end;end;********************************************************************** procedure Tinoutform.SpeedButton1Click(Sender: TObject);var s:integer;begin file://入庫管理添加按鈕事件
if Edit1.Text<>NULL then MessageDlg(?請輸入完整的入庫信息和圖書信息,然后單擊確定按鈕。?, mtInformation,[mbok],0)else begin
if(Edit2.Text=??)or(Edit3.Text=??)or(Edit4.Text=??)or(Edit5.Text=??)
then begin
MessageDlg(?請輸入完整的入庫信息!?,mtInformation,[mbok],0);
Edit2.SetFocus;
end
else begin
with datamoduleform.InQuery do file://將找到的圖書信息顯示
begin
close;
SQL.Clear;SQL.Add(?insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)?);file://向入庫信息表中插入記錄
Parameters.ParamByName(?InID?).Value:=Edit26.Text;file://向Edit框取值
Parameters.ParamByName(?BookID?).Value:=Edit13.Text;
Parameters.ParamByName(?EmpID?).Value:=Edit2.Text;
Parameters.ParamByName(?ShopID?).Value:=Edit3.Text;
Parameters.ParamByName(?Number?).Value:=Edit4.Text;
Parameters.ParamByName(?InDate?).Value:=Edit5.Text;
execSQL;
end;
Edit12.ReadOnly:=False;
S:=StrToInt(Edit12.Text)+StrToInt(Edit4.Text);file://計算入庫后庫存圖書數量
Edit12.Text:=IntToStr(s);file://將修改后的庫存圖書數量顯示
Edit12.ReadOnly:=true;
with datamoduleform.BookQuery do
file://修改庫存記錄中圖書數量
begin
close;
SQL.Clear;
SQL.Add(?update BookRecord set Number1=:Number where BookID=:BookID?);
Parameters.ParamByName(?Number?).Value:=s;
Parameters.ParamByName(?BookID?).Value:=Edit13.Text;
execSQL;
file://提交SQL語句
MessageDlg(?記錄已成功添加!?,mtInformation,[mbOK],0);
Edit13.SetFocus;
end;
end;end;end;********************************************************************** procedure Tinoutform.SpeedButton2Click(Sender: TObject);begin
file://入庫管理確定按鈕事件
if(Edit2.Text=??)or(Edit3.Text=??)or(Edit4.Text=??)or(Edit5.Text=??)
or(Edit6.Text=??)or(Edit7.Text=??)or(Edit8.Text=??)or(Edit9.Text=??)
or(Edit10.Text=??)or(Edit11.Text=??)or(Edit25.Text=??)
then begin file://判斷輸入信息的完整性
MessageDlg(?請輸入所需的全部入庫信息!?,mtInformation,[mbok],0);Edit2.SetFocus;end else begin
with datamoduleform.InQuery do file://入庫信息添加
begin
close;
SQL.Clear;SQL.Add(?insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)?);
file://向入庫信息表中插入記錄
Parameters.ParamByName(?InID?).Value:=Edit26.Text;
Parameters.ParamByName(?BookID?).Value:=Edit1.Text;
Parameters.ParamByName(?EmpID?).Value:=Edit2.Text;
Parameters.ParamByName(?ShopID?).Value:=Edit3.Text;
Parameters.ParamByName(?Number?).Value:=Edit4.Text;
Parameters.ParamByName(?InDate?).Value:=Edit5.Text;
execSQL;
end;
with datamoduleform.BookQuery do
begin
close;
SQL.Clear;
file://在完成入庫信息的添加后,修改庫存記錄 SQL.Add(?insert into BookRecord values(:BookID,:BookName,:Author, :Publisher,:PubDate,:Price,:BookType,:Number,:Addration)?);
Parameters.ParamByName(?BookID?).Value:=Edit1.Text;
Parameters.ParamByName(?BookName?).Value:=Edit6.Text;
Parameters.ParamByName(?Author?).Value:=Edit7.Text;
Parameters.ParamByName(?Publisher?).Value:=Edit8.Text;
Parameters.ParamByName(?PubDate?).Value:=Edit9.Text;
Parameters.ParamByName(?Price?).Value:=Edit10.Text;
Parameters.ParamByName(?BookType?).Value:=Edit11.Text;
Parameters.ParamByName(?Number?).Value:=Edit4.Text;
Parameters.ParamByName(?Addration?).Value:=Edit25.Text;
execSQL;
end;
MessageDlg(?記錄添加成功!?,mtInformation,[mbok],0);
end;end;********************************************************************** procedure Tinoutform.SpeedButton11Click(Sender: TObject);begin file://新書入庫按鈕事件
Edit13.Text:=??;Edit13.Color:=clMenu;with datamoduleform.InQuery do file://自動入庫編號的獲取
begin close;SQL.Clear;SQL.Add(?select * from InRecord where InID>=All(select InID from InRecord)?);
open;Edit26.Text:=FieldValues[?InID?]+1;
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;end;with datamoduleform.BookQuery do file://自動圖書編號的獲取
begin close;
SQL.Clear;
SQL.Add(?select * from BookRecord where BookID>=All(select BookRecord)?);
file://找到庫存圖書編號中最大的一個
open;
Edit1.ReadOnly:=false;
Edit1.Text:=FieldValues[?BookID?]+1;file://顯示自動生成的圖書編號
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;end;Edit2.Text:=??;Edit3.Text:=??;Edit4.Text:=??;Edit5.Text:=??;
Edit6.ReadOnly:=false;Edit6.Text:=??;Edit6.Color:=clWindow;
Edit7.ReadOnly:=false;Edit7.Text:=??;Edit7.Color:=clWindow;
Edit8.ReadOnly:=false;Edit8.Text:=??;Edit8.Color:=clWindow;
Edit9.ReadOnly:=false;Edit9.Text:=??;Edit9.Color:=clWindow;
Edit10.ReadOnly:=false;Edit10.Text:=??;Edit10.Color:=clWindow;
Edit11.ReadOnly:=false;Edit11.Text:=??;Edit11.Color:=clWindow;
Edit12.ReadOnly:=false;Edit12.Text:=??;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=??;Edit25.Color:=clWindow;end;procedure Tinoutform.SpeedButton22Click(Sender: TObject);var s:integer;begin file://出庫管理確定按鈕事件
if(Edit24.Text=??)or(Edit27.Text=??)or(Edit28.Text=??)then begin MessageDlg(?請輸入完整的出庫信息!?,mtInformation,[mbok],0);Edit24.SetFocus;end else begin if Edit27.Text>Edit21.Text file://檢查出庫數量是否小于庫存數量 then begin MessageDlg(?庫存中的圖書數量不夠!?,mtInformation,[mbok],0);Edit27.Text:=??;Edit27.SetFocus;
end else begin with datamoduleform.OutQuery do begin
BookID from close;SQL.Clear;SQL.Add(?insert into OutRecord values(:OutID,:BookID,:EmpID, :Number,:OutTime)?);file://添加出庫記錄
Parameters.ParamByName(?OutID?).Value:=Edit23.Text;Parameters.ParamByName(?BookID?).Value:=Edit14.Text;Parameters.ParamByName(?EmpID?).Value:=Edit24.Text;Parameters.ParamByName(?Number?).Value:=Edit27.Text;Parameters.ParamByName(?OutTime?).Value:=Edit28.Text;execSQL;end;Edit21.ReadOnly:=False;s:=StrToInt(Edit21.Text)-StrToInt(Edit27.Text);file://計算出庫后庫存圖書數量 Edit21.Text:=IntToStr(s);file://顯示出庫后庫存圖書數量 Edit21.ReadOnly:=True;with datamoduleform.BookQuery do begin
file://修改庫存圖書數量 close;SQL.Clear;SQL.Add(?update BookRecord set Number1=:Number where BookID=:BookID?);Parameters.ParamByName(?Number?).Value:=s;
Parameters.ParamByName(?BookID?).Value:=Edit14.Text;execSQL;end;MessageDlg(?出庫記錄添加成功!?,mtInformation,[mbok],0);Edit14.Text:=??;Edit14.SetFocus;end;end;end;
§5.5 查詢功能的實現
查詢功能包括員工信息查詢,供應商信息查詢,入庫信息查詢和出庫信息查詢。由于每一個功能的實現都差不太多,而且其窗體也差不太多,所以在這里只給出員工信息查詢窗體及其源代碼。
圖5.6 員工信息查詢窗體
procedure Tfindempform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3 :String;begin
file://員工記錄查詢窗體查找按鈕事件 with datamoduleform.EmpQuery do begin close;SQL.Clear;SQL.Add(?select * from Employee?);
SQL.Add(?where EmployeeID Like :EmpID and EmployeeName Like :Name and Grade Like :Grade?);
file://實現模糊查詢功能
if Edit1.Text<>?? then s1:=?%?+Edit1.Text+?%? else s1:=?%?;Parameters.ParamByName(?EmpID?).Value:=s1;
if Edit2.Text<>?? then s2:=?%?+Edit2.Text+?%? else s2:=?%?;Parameters.ParamByName(?Name?).Value:=s2;
if Edit3.Text<>?? then s3:=?%?+Edit3.Text+?%? else s3:=?%?;Parameters.ParamByName(?Grade?).Value:=s3;open;if FieldValues[?EmployeeID?]<>NULL
then findempform.Close
file://在找到記錄的情況下關閉查找窗口 else begin MessageDlg(?沒有找到你所需要的記錄!?,mtInformation,[mbOK],0);Edit1.Text:=??;Edit2.Text:=??;Edit3.Text:=??;Edit1.SetFocus;close;SQL.Clear;SQL.Add(?select * from Employee?);file://刷新員工信息窗口 open;end;end;end;§5.6 系統登陸窗體模塊的實現
由于系統登陸窗體中有一幅彩圖,在這里不便給出,而只給出了系統的實現。var keyname: string;file://定義了一個全局變量,在key2中有調用 procedure Tkeyform.SpeedButton1Click(Sender: TObject);var s:string;
file://登陸窗口登陸按鈕事件 begin if(Edit1.Text=??)then begin MessageDlg(?清輸入登陸姓名和密碼!?,mtInformation,[mbok],0);Edit1.SetFocus;end else begin datamoduleform.KeyTable.Active:=true;if not datamoduleform.KeyTable.Locate(?KeyName?,Edit1.Text,[])
file://判斷登陸名是否存在 then begin MessageDlg(?登陸名錯誤,請重新輸入!?,mtInformation,[mbok],0);Edit1.Text:=??;Edit1.SetFocus;end else begin with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(?select * from Key where KeyName=:KeyName?);Parameters.ParamByName(?KeyName?).Value:=Edit1.Text;open;s:=FieldValues[?KeyNo?];end;if s<>Edit2.Text file://判斷登陸密碼是否正確 then begin MessageDlg(?登陸密碼錯誤,請重新輸入!?,mtInformation,[mbok],0);Edit2.Text:=??;Edit2.SetFocus;end else begin keyname:=Edit1.Text;keyform.Hide;mainform.Show;mainform.WindowState:=wsMaximized;end;end;end;end;§5.7 用戶管理功能的實現 5.7.1 用戶管理主窗體
圖5.7 用戶管理主窗體 5.7.2 密碼修改窗體模塊的實現
圖5.8 密碼修改窗體
procedure Tkey2form.SpeedButton1Click(Sender: TObject);begin file://密碼修改窗口修改按鈕事件 if(Edit1.Text=??)or(Edit2.Text=??)or(Edit3.Text=??)then begin MessageDlg(?請輸入完整的信息。?,mtInformation,[mbok],0);Edit1.SetFocus;end else begin if Not datamoduleform.KeyTable.Locate(?KeyNo?,Edit1.Text,[])then begin MessageDlg(?原密碼輸入錯誤,不能修改新密碼!?,mtInformation,[mbok],0);Edit1.Text:=??;Edit2.Text:=??;Edit3.Text:=??;Edit1.SetFocus;end else begin if Edit2.Text<>Edit3.Text then begin MessageDlg(?兩次密碼輸入不同,請重新輸入新密碼!?,mtInformation,[mbok],0);Edit2.Text:=??;Edit3.Text:=??;Edit2.SetFocus;end else begin
file://在數據庫中修改密碼 with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(?update key set KeyNo=:KeyNo where KeyName=:KeyName?);Parameters.ParamByName(?KeyName?).Value:=keyname;Parameters.ParamByName(?KeyNo?).Value:=Edit2.Text;execSQL;MessageDlg(?密碼修改成功!?,mtInformation,[mbok],0);key2form.Close;end;end;end;end;end;5.7.3 用戶注冊窗體模塊的實現
圖5.9 用戶注冊窗體
procedure Tkey3form.SpeedButton1Click(Sender: TObject);begin file://用戶注刪窗口注刪按鈕事件 if(Edit1.Text=??)or(Edit2.Text=??)or(Edit3.Text=??)then begin MessageDlg(?請輸入完整的信息!?,mtInformation,[mbok],0);Edit1.SetFocus;end else begin if datamoduleform.KeyTable.Locate(?KeyName?,Edit1.Text,[])
file://判斷用戶名是否存在,系統不允許用戶名重復 then begin MessageDlg(?用戶名已存在,請輸入新的用戶名和密碼!?, mtInformation,[mbok],0);Edit1.Text:=??;Edit2.Text:=??;Edit3.Text:=??;Edit1.SetFocus;end else begin if Edit2.Text<>Edit3.Text then begin MessageDlg(?您輸入的兩個密碼不相同,請重新輸入!?,mtInformation,[mbok],0);Edit2.Text:=??;Edit3.Text:=??;Edit2.SetFocus;end else begin with datamoduleform.KeyQuery do
file://在數據庫中添加該用戶 begin close;SQL.Clear;SQL.Add(?insert into Key values(:KeyName,:KeyNo)?);Parameters.ParamByName(?KeyName?).Value:=Edit1.Text;Parameters.ParamByName(?KeyNo?).Value:=Edit2.Text;execSQL;end;MessageDlg(?新用戶添加成功,您可以繼續添加用戶,或按“取消”退出。?,mtInformation,[mbok],0);
Edit1.Text:=??;Edit2.Text:=??;Edit3.Text:=??;Edit1.SetFocus;end;end;end;end;5.7.4 用戶注銷窗體模塊的實現
圖5.10 用戶注銷窗體
procedure Tkey4form.SpeedButton1Click(Sender: TObject);var s:string;begin file://用戶注銷窗口注銷按鈕事件 if(Edit1.Text=??)or(Edit2.Text=??)
then MessageDlg(?請輸入完整的信息!?,mtInformation,[mbok],0)else begin if Not datamoduleform.KeyTable.Locate(?KeyName?,Edit1.Text,[])
file://判斷用戶名是否存在,用戶名必須存在,才可以刪除 then begin MessageDlg(?您所輸入的用戶名不存在,請重新輸入或按“取消”退出。?, mtInformation,[mbok],0);Edit1.Text:=??;Edit2.Text:=??;Edit1.SetFocus;end else begin with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(?select * from Key where KeyName=:KeyName?);Parameters.ParamByName(?KeyName?).Value:=Edit1.Text;open;s:=FieldValues[?KeyNo?];end;if s<>Edit2.Text file://判斷該用戶名下的密碼是否正確 then begin MessageDlg(?您所輸入的密碼不正確,請重新輸入或按“取消”退出。?, mtInformation,[mbok],0);Edit2.Text:=??;Edit2.SetFocus;end else begin
file://從數據庫中刪除該用戶 with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(?delete from Key where KeyName=:KeyName?);Parameters.ParamByName(?KeyName?).Value:=Edit1.Text;execSQL;end;MessageDlg(?用戶已成功刪除,您可以繼續刪除用戶,或按“取消”退出。?, mtInformation,[mbok],0);Edit1.Text:=??;Edit2.Text:=??;Edit1.SetFocus;end;end;end;end;
結束語
本系統是一個面向小型圖書企業,具有一定實用性的數據庫信息管理系統。它主要完成對圖書倉庫的一系列管理,包括入庫、出庫、庫存以及員工和供應商信息管理。本系統采用當前流行的面向對象的開發工具—Delphi來完成整個系統的設計,在數據庫的設計上利用了Access的便利性和實用性。
本系統具有相當的實用功能。在查詢方面,系統實現了多條件任意字段的模糊查詢,同時在分類查詢上實現了動態生成,系統可以自動識別用戶不同的輸入。在圖書入庫、出庫和庫存三者之間建立了良好的鏈接關系,某一部分地修改均會自動引發系統對與其相關的部分進行連鎖修改。在用戶管理方面,系統較好地實現了用戶注冊,用戶注銷和密碼修改等各項功能。系統在設計過程中不可避免地遇到了各種各樣的問題,由于整個系統完全都是由個人設計的,有關Delphi許多細節問題都要靠自己去摸索,加之本人水平有限,并沒有完全地理解Delphi的強大功能,而且還存在著許多不足之處。如:
※
受開發條件和開發時間的限制,本系統只利用了本地數據庫Access,它同應用程序處于同一系統中,能存儲的數據量也有一定限制,并沒有發揮出Delphi其數據庫方面的優勢; ※
報表打印功能尚不夠全面完善,不能實現動態報表;
※
在一些數據輸入時沒有及時的進行數據格式校驗,不能保證數據輸入的絕對正確性。※
由于時間關系,系統功能實現不夠完善,使用不是很方便,比如,沒有實現多條記錄的連鎖刪除和添加以及數據的導入功能。這些都是需要完善的地方,該系統離實際使用也還有相當的距離,需要我進行不斷地補充和完善。
通過本次畢業設計我學到了不少新的東西,也發現了大量的問題,有些在設計過程中已經解決,有些還有待今后慢慢學習。只要學習就會有更多的問題,有更多的難點,但也會有更多的收獲。
考 文 獻
[1] 鄭榮貴、黃平、谷會東,Delphi 6.0數據庫開發與應用,中科多媒體電子出版社,2002 [2] 伍俊良,Delphi 6控件應用實例教程,北京希望電子出版社,2002 [3] 盧國俊,Delphi 6數據庫開發,電子工業出版社,2002 [4] 邊萌,Delphi 編程起步,機械工業出版社,2002 [5] 伍俊良,Delphi 6課程設計案例精編,中國水利水電出版社,2002 [6] 丁寶康,數據庫原理,經濟科學出版社,2000 [7] 陸麗娜,軟件工程,經濟科學出版社,2000
第五篇:圖書倉庫管理系統的設計
圖書倉庫管理系統的設計(1)摘 要
本系統主要完成對圖書倉庫的庫存管理,包括圖書入庫、出庫、庫存,員工信息,供應商信息以及密碼管理等六個方面。系統可以完成對各類信息的瀏覽、查詢、添加、刪除、修改、報表等功能。
系 統的核心是入庫、庫存和出庫三者之間的聯系,每一個表的修改都將聯動的影響其它的表,當完成入庫或出庫操作時系統會自動地完成庫存的修改。查詢功能也是系 統的核心之一,在系統中即有單條件查詢和多條件查詢,也有精確查詢和模糊查詢,系統不僅有靜態的條件查詢,也有動態生成的條件查詢,其目的都是為了方便用 戶使用。系統有完整的用戶添加、刪除和密碼修改功能,并具備報表打印功能。
系統采用Microsoft Office中的Access 2000來設計數據庫,并使用當前優秀的開發工具—Delphi 6.0,它有著最為靈活的數據庫結構,對數據庫應用有著良好的支持。
論文主要介紹了本課題的開發背景,所要完成的功能和開發的過程。重點的說明了系統設計的重點、設計思想、難點技術和解決方案。
關鍵字:數據庫,SQL語言,Delph 6,數據庫組件,倉庫管理
目 錄
第一章 引言 ?????????????????????????????1
1.1 課題來源 ??????????????????????????1 1.2 開發工具的選擇 ???????????????????????2 1.3 所做的主要工作 ???????????????????????3 第二章 數據庫概論 ??????????????????????????4
2.1 數據庫的發展 ????????????????????????4 2.1.1 數據庫的發展 ??????????????????????4 2.1.2 數據庫階段的特點 ????????????????????5 2.1.3 數據庫技術 ???????????????????????6 2.2 數據庫理論基礎 ???????????????????????7 2.2.1 數據庫模型 ???????????????????????7 2.2.2 數據庫體系結構 ????????????????????10
2.2.3 數據的獨立性 ?????????????????????11 2.2.4 范式 ?????????????????????????11 2.3 SQL語言基礎 ???????????????????????13 2.3.1 SQL簡介 ???????????????????????13 2.3.2 SQL查詢 ???????????????????????13 2.3.3 SQL數據更新 ?????????????????????14 第三章數據庫開發工具 ???????????????????????16 3.1 Delphi 6.0 簡介 ???????????????????????16 3.2 Delphi 6.0 控件 ???????????????????????17
3.2.1 ADO數據訪問組件 ???????????????????17 3.2.2 數據控制類DataControl ?????????????????18 3.2.3 數據訪問類DataAccess ?????????????????18 3.2.4 SQL語言在Delphi中的應用 ???????????????19 3.3 Access 簡介 ????????????????????????21 第四章 系統總體設計 ????????????????????????23
4.1 系統需求分析 ???????????????????????23 4.2 系統概要設計 ???????????????????????25 4.2.1 系統結構設計 ?????????????????????25 4.2.2 數據庫設計 ??????????????????????27
4.2.2.1 ER圖設計 ????????????????????27 4.2.2.2 數據庫表格設計??????????????????29 4.3系統詳細設計????????????????????????34 第五章 系統應用程序設計 ??????????????????????37
5.1 系統窗體模塊組成??????????????????????37 5.2 數據模塊窗體設置??????????????????????38 5.3 主窗體功能模塊的實現????????????????????39 5.4 入庫、出庫窗體模塊的實現??????????????????43 5.5 查詢功能的實現???????????????????????51 5.6 系統登陸窗體模塊的實現???????????????????52 5.7 用戶管理功能的實現?????????????????????54 5.7.1 用戶管理主窗體 ????????????????????54 5.7.2 密碼修改窗體模塊的實現 ????????????????54 5.7.3 用戶注冊窗體模塊的實現 ????????????????55 5.7.4 用戶注銷窗體模塊的實現 ????????????????57 結束語 ???????????????????????????????59 致謝 ????????????????????????????????60 參考文獻 ??????????????????????????????61 第一章 引 言 §1.1 課題來源
隨 著社會經濟的迅速發展和科學技術的全面進步,計算機事業的飛速發展,以計算機與通信技術為基礎的信息系統正處于蓬勃發展的時期。隨著經濟文化水平的顯著提 高,人們對生活質量及工作環境的要求也越來越高。書籍做為人類的精神食糧,在現代社會中越來越受到重視,大量的書籍出現在市場上,人們有了各種各樣不同的 選擇。與此同時,為了管理大量的圖書,圖書倉庫也大量的出現,倉庫的管理問題也就提上了日程。隨著圖書的大量增加,其管理難度也越來越大,如何優化倉庫的 日常管理也就成為了一個大眾化的課題。在計算機飛速發展的今天,將計算機這一信息處理利器應用于倉庫的日常管理已是勢必所然,而且這也將為倉庫管 理帶來前所未有的改變,它可以帶來意想不到的效益,同時也會為企業的飛速發展提供無限潛力。采用計算機管理信息系統已成為倉庫管理科學化和現代化的重要標 志,它給企業管理來了明顯的經濟效益和社會效益。主要體現在:
極大提高了倉庫工作人員的工作效率,大大減少了以往入出存流程繁瑣,雜亂,周期長的弊端。
基于倉庫管理的全面自動化,可以減少入庫管理、出庫管理及庫存管理中的漏洞,可以節約不少管理開支,增加企業收入。
倉庫的管理的操作自動化和信息的電子化,全面提高了倉庫的管理水平。
隨 著我國改革開放的不斷深入,經濟飛速的發展,企業要想生存、發展,要想在激烈的市場競爭中立于不敗之地,沒有現代化的管理是萬萬不行的,倉庫管理的全面自 動化、信息化則是其中極其重要的部分。為了加快倉庫管理自動化的步伐,提高倉庫的管理業務處理效率,建立倉庫管理系統已變得十分心要。入庫、庫 存、出庫還是現在企業圖書倉庫管理的常規基本模式,雖然,最近又出現了很多新的管理模式,如:基于零庫存思想的沃爾瑪特管理方式,但這些新的思想在中國大 部分企業的管理中還是難以實現的。所以如何設計好倉庫管理系統,盡可能地減少倉庫管理的重復性和低效性就成為當前最為重要的問題。圖書倉庫管理的核心是入 庫、庫存和出庫之間的聯系,如何處理好三者之間的關系是系統最為關鍵的部分。另外,員工信息和供應商信息管理也是倉庫管理中一個必不可少的部分,它提供著 與入庫和出庫相關的地一些信息,使得整個系統更加完整,更加實用。
通過對倉庫管理日常工作的詳細調查,搜集了大量的資料,從系統結構的組織,功能的實現,技術的要求以及可行性等多方面進行考慮,認為本課題是一個適應現今圖書倉庫管理需求的計算機信息管理系統,具有一定的實際開發價值和使用價值。
§1.2 開發工具的選擇
自Java 誕生以來,隨著Internet技術的普及和應用需求的變化,以第四代語言為主的應用開發產品發生了較大的變化,它們不僅已成為人們開發應用的開發工具,而且很多產品已發展成為一種強有力的應用開發環境。這些新型的開發工具通常以一種集成軟件包的形式提供給開發人員,被稱為Studio(工作室)或 Suite(程序組)。例如,微軟的Visual Studio 6.0,Borland公司的Delphi 6.0等數據庫輔助開發工具。
現在,市場上可以選購的應用開發產品很多,流行的也有數十種。目前在我國市場上最為流行、使用最多、最為先進的可用作企業級開發工具的產品有: Microsoft公司的Visual Basic 6.0版 Microsoft公司的Visual C++6.0版 Borland公司的Delphi 6.0版
在 目前市場上這些眾多的程序開發工具中,有些強調程語言的彈性與執行效率;有些則偏重于可視化程序開發工具所帶來的便利性與效率的得高,各有各的優點和特 色,也滿足了不同用戶的需求。然而,語言的彈性和工具的便利性是密不可分的,只有便利的工具,卻沒有彈性的語言作支持,許多特殊化的處理動作必需要耗費數 倍的工夫來處理,使得原來所標榜的效率提高的優點失去了作用;相反,如果只強調程語言的彈性,卻沒有便利的工具作配合,會使一些即使非常簡單的界面處理動 作,也會嚴重地浪費程序設計師的寶貴時間。而Delphi是一個非常理想選擇。Delphi 6 是操作系統中快速應用開發環境的最新版本。它也是當前Windows平臺上第一個全面支持最新Web服務的快速開發工具。無論是企業級用戶,還是個人開發 者,都能夠利用Delphi 6 輕松、快捷地構建新一代電子商務應用。Delphi 6 是惟一支持所有新出現的工業標準的RAD環境,包括XML(擴展標記語言)/XSL(可擴展樣式語言),SOAP(簡單對象存取協議)和WSDL(Web 服務器描述語言)等。Delphi 6 是可視化的快速應用程序開發語言,它提供了可視化的集成開發環境,這一環境為應用程序設計人員提供了一系列靈活而先進的工具,可以廣泛地用于種類應用程序 設計。在Delphi 6 的集成開發環境中,用戶可以設計程序代碼、運行程序、進行程序錯誤的調試等,可視化的開發方法降低了應用程序開發的難度。Delphi的基礎編程語言是具 有面向對象特性的Pascal語言,即Object Pascal。Object Pascal具有代碼穩定、可讀性好、編譯速度快等優點,并將面向對象的概念移植到了Pascal語言中,使這種基礎語言有了新的發展空間。使用 Delphi 6.0,我們幾乎可以作任何事情,還可以撰寫種各種類型的應用程序,動態鏈接庫(DLL)、CON、或CORBA對象,CGI/ISAPI程序,Microsoft Back Office應用程序。程序的規模小到簡單的個人數據庫應用,大到復雜的企業的多層次分布式系統,都可以使用Delphi進行開發,其友好的集成開發界 面,可視化的雙向開發模式,良好的數據庫應用支持高效的程序開發和程序運行,備受廣大程序開發人員的好評。尤其是Delphi對數據庫應用的強大支持,大 大提高了數據庫應用軟件開發的效率,縮短了開發周期,深受廣大數據庫應用程序設計人員的喜愛。Delphi為數據庫應用開發人員提供了豐富的數據庫開發組 件,使數據庫應用開發功能更強大,控制更靈活,編譯后的程序運行速度更快。§1.3 本文所做工作
引言部分介紹了本系統的課題來源以及對數據庫開發工具的選擇。
第二章介紹了數據庫的發展,關系數據庫,數據庫體系結構,并系統介紹了SQL語言,為設計和理解應用程序做了鋪墊。第三章系統介紹了Delphi 6.0及其部分控件,SQL語言在Delphi 6.0中的應用,以及Access等。
第四章是本文的主體,按照軟件工程的要求,從需求分析開始,經過概要設計最后到詳細設計,完成對整個系統的設計。
第五章根據第四章的設計結果利用Access 2000和Delphi 6.0進行了具體的窗體和應用程序設計。
總結部分介紹了設計體會和編程體會,并指出了系統設計中的不足和改進的方向
圖書倉庫管理系統的設計(2)第二章 數據庫概論 §2.1 數據庫的發展
數據庫處理在信息系統的研究中一直是非常重要的主題,然而,近年來,隨著World Wide Web(www.tmdps.cn公司的TOTAL等
(3)關系模型。關系模型的主要是用二維表格結構表達實體集,用外鍵表示實體間聯系。關系模型是由若干個關系模式組成的集合。關系模式相當于前面提到的記錄類型,它的實例稱為關系,每個關系實際上是一張二維表格。
關 系模型和層次、網狀模型的最大判別是用關鍵碼而不是用指針導航數據,表格簡單用戶易懂,編程時并不涉及存儲結構,訪問技術等細節。關系模型是數學化模型。SQL語言是關系數據庫的標準化語言,已得到了廣泛的應用。20世紀70年代對關系數據庫的研究主要集中在理論和實驗系統的開發方面。80年代初才形成產 品,但很快得到廣泛的應用和普及,并最終取代了層次、網狀數據庫產品。現在市場上典型的關系DBMS產品有DB2、ORACLE、SYBASE、INFORMIX和微機型產品Foxpro、Access等。
關系模型和網狀、層次模型的最大區別是:關系模型用表格數據而不是通過指針鏈來表示和實現實體間聯系。關系模型的數據結構簡單、易懂。只需用簡單的查詢語句就可對數據庫進行操作。
關系模型是數學化的模型,可把表格看成一個集合,因此集合論、數理邏輯等知識可引入到關系模型中來。關系模型已是一個成熟的有前途的模型,已得到廣泛應用。(4)面向對象模型。目前,關系數據庫的使用已相當普遍,但是,現實世界中仍然存在著許多含有復雜數據結構的應用領域,例如,CAD數據、圖形數據等,而關系模 型在這方面的處理能力就顯得力不從心。因此,人們需要更高級的數據庫技術來表達這類信息。面向對象的概念最早出現在程序設計語言中,隨后迅速滲透到計算機 領域的每一個分支。面向對象數據庫是面向對象概念與數據庫技術相結合的產物。
面向對象模型能完整地描述現實世界的數據結構,具有豐富的表達能力,但模型相對較復雜,涉及的知識面也廣,因此面向對象數據庫尚未達到關系數據庫那樣的普及程度。
2.2.2 數據庫體系結構
數 據庫的體系結構分三級:內部級(internal),概念級(conceptual)和外部級(external)。這個三級結構有時也稱為“三級模式結 構”,或“數據抽象的三個級別”,最早是在1971年通過的DBTG報告中提出,后來收入在1975年的美國ANSI/SPARC報告中。雖然現在 DBMS的產品多種多樣,在不同的操作系統支持下工作,但是大多數系統在總的體系結構上都具有三級模式的結構特征。從某個角度看到的數據特性稱為“數據視 圖”(data view)。
外部級最接近用戶,是單個用戶所能看到的數據特性。單個用戶使用的數據視圖的描述稱為“外模式”。
概念級涉及到所有用戶的數據定義,是全局的數據視圖。全局數據視圖的描述稱為“概念模式”。
內部級最接近于物理存儲設備,涉及到實際數據存儲的結構。物理存儲數據視圖的描述稱為“內模式”。
數據庫的三級模式結構是數據的三個抽象級別。它把數據的具體組織留給DBMS去做,用戶只要抽象地處理數據,而不必關心數據在計算機中的表示和存儲,這樣就減輕了用戶使用系統的負擔。
三級結構之間往往差別很大,為了實現這三個抽象級別的聯系和轉換,DBMS在三級結構之間提供兩個層次的映象(mappings):外模式/模式映象,模式/內模式映象。此處模式是概念模式的簡稱。2.2.3 數據的獨立性
由于數據庫系統采用三級模式結構,因此系統具有數據獨立性的特點。在數據庫技術中,數據獨立性是指應用程序和數據之間相互獨立,不受影響。數據獨立性分成物理數據獨立性和邏輯數據獨立性兩級。(1)物理數據獨立性
如果數據庫的內模式要進行修改,即數據庫的存儲設備和存儲方法有所變化,那么模式/內模式映象也要進行相當的修改,使概念模式盡可能保持不變。也就是對內模式的修改盡量不影響概念模式,當然,對于外模式和應用程序的影響更小,這樣,我們稱數據庫達到了物理數據獨立性。(2)邏輯數據獨立性
如果數據庫的概念模式要進行修改,譬如增加記錄類型或增加數據項,那么外模式/模式映象也要進行相應的修改,使外模式盡可能保持不變。也就是對概念模式的修改盡量不影響外模式和應用程序,這樣,我們稱數據庫達到了邏輯數據獨立性。
現有關系系統產品均提供了較高的物理獨立性,而對邏輯獨立性的支持尚有欠缺,例如,對外模式的數據更新受到限制等。2.2.4 范式
建 立起一個良好的數據指標體系,是建立數據結構和數據庫的最重要的一環。一個良好的數據指標體系是建立DB的必要條件,但不是充分條件。我們完全可以認為所 建指標體系中的一個指標類就是關系數據庫中的一個基本表,而這個指標類下面的一個個具體指標就是這個基本表中的一個字段。但如果直接按照這種方式建庫顯然 還不能算最佳。對于指標體系中數據的結構在建庫前還必須進行規范化的重新組織。在數據的規范化表達中,一般將一組相互關聯的數據稱為一個關系(relation),而在這個關系下的每個數據指標項則被稱為數據元素(data element),這種關系落實到具體數據庫上就是基本表,而數據元素就是基本表中的一個字段(field)。規范化表達還規定在每一個基本表中必須定義 一個數據元素為關鍵字(key),它可以唯一地標識出該表中其它相關的數據元素。在規范化理論中表是二維的,它有如下四個性質:
在表中的任意一列上,數據項應屬于同一個屬性(如圖中每一列都存放著不同合同記錄的同一屬性數據)。
表中所有行都是不相同的,不允許有重復組項出現(如圖中每一行都是一個不同的合同記錄)。
在表中,行的順序無關緊要(如圖中每行存的都是合同記錄,至于先放哪一個合同都沒關系)。
在表中,列的順序無關緊要,但不能重復(如圖中合同號和合同名誰先誰后都沒關系,但二者不可重復或同名)。
在 對表的形式進行了規范化定義后,數據結構還有五種規范化定義,定名為規范化模式,稱為范式。在這五種范式中,一般只用前三種,對于常用系統就足夠了。而且 這五種范式是“向上兼容”的,即滿足第五范式的數據結構自動滿足一、二、三、四范式,滿足第四范式的數據結構自動滿足第一、二、三范式,??,依此類推。
第 一范式(first normal form,簡稱1st NF)就是指在同一表中沒有重復項出現,如果有則應將重復項去掉。這個去掉重復項的過程就稱之為規范化處理。在本文所討論的開發方法里,1st NF實際上是沒有什么意義的。因為我們按規范化建立的指標體系和表的過程都自動保證了所有表都滿足1st NF。
第二范式(second normal form,簡稱 2nd NF)是指每個表必須有一個(而且僅一個)數據元素為主關鍵字(primary key),其它數據元素與主關鍵字一一對應。例如,在圖l9.7中如果我們將合同號定義為主關鍵字(其它數據元素中的記錄數據都有可能重名,故不能作為主 關鍵字),故只要知道了一個合同記錄的合同號,就可以唯一地在同一行中找到該合同的任何一項具體信息。通常我們稱這種關系為函數依賴(functional depEndence)關系。即表中其它數據元素都依賴于主關鍵字,或稱該數據元素唯一地被主關鍵字所標識。
第三范式(third normal form,簡稱 3rd NF)就是指表中的所有數據元素不但要能夠唯一地被主關鍵字所標識,而且它們之間還必須相互獨立,不存在其它的函數關系。也就是說對于一個滿足了 2nd NF的數據結構來說,表中有可能存在某些數據元素依賴于其它非關鍵宇數據元素的現象,必須加以消除。
為防止數據庫出現更新異常、插入異常、刪除異常、數據冗余太大等現象,關系型數據庫要盡量按關系規范化要求進行數據庫設計。
§2.3 SQL語言基礎 2.3.1 SQL簡介
用戶對數據庫的使用,是通過數據庫管理系統提供的語言來實現的。不同的數據庫管理系統提供不同的數據庫語言。關系數據庫管理系統幾乎都提供關系數據庫標準語言——SQL。
SQL 的全稱是Structured Query Language,即結構化查詢語言。SQL語句可以從關系數據庫中獲得數據,也可以建立數據庫、增加數據、修改數據。1986年ANSI采用SQL語言 作為關系數據庫系統的標準語言,后被國際化標準組織(ISO)采納為國際標準。SQL語言使用方便、功能豐富、簡潔易學,是操作數據庫的工業標準語言,得 到廣泛地應用。例如關系數據庫產品DB2、ORACLE等都實現了SQL語言。同時,其它數據庫產品廠家也紛紛推出各自的支持SQL的軟件或者與SQL的 接口軟件。這樣SQL語言很快被整個計算機界認可。SQL語言是一種非過程化語言,它一次處理一個記錄集合,對數據提供自動導航。SQL語言允許 用戶在高層的數據結構上工作,而不對單個記錄進行操作。SQL語言不要求用戶指定數據的存取方法,而是使用查詢優化器,由系統決定對指定數據存取的最快速 手段。當設計者在關系表上定義了索引時,系統會自動利用索引進行快速檢索,用戶不需知道表上是否有索引或者有什么類型的索引等細節。
SQL語言可以完成許多功能,例如: ● 查詢數據
● 在數據庫表格中插入、修改和刪除記錄 ● 建立、修改和刪除數據對象 ● 控制對數據和數據對象的存取 ● 確保數據庫的一致性和完整性等 2.3.2 SQL查詢
數據查詢是關系運算理論在SQL語言中的主要體現,SELECT 語句是SQL查詢的基本語句,當我們在對一個數據庫進各種各樣的操作時,使用的最多的就是數據查詢,在以SQL為基礎的關系數據庫中,使用的最多的就是SELECT查詢語句。SELECT語句的完整句法如下:
SELECT 目標表的列名或列表達式序列 FROM 基本表和(或)視圖序列 [WHERE 行條件表達式] [GROUP BY 列名序列] [HAVING 組條件表達式] [ORDER BY列名 [ASC│DEAC]?]
我 在SELECT語句中還使用了大量的保留字和通配符以進行各種各樣的條件查詢。在系統中有大量的查詢按鈕,其使用了大量的查詢語句,而且這些查詢語句大部 分使用的是模糊查詢,所以大量的使用了模式匹配符LIKE(判斷值是否與指定的字符通配格式相符)。在包含LIKE的查詢語句中可以使用兩個通配符:%(百分號):與零個或多個字符組成的字符串匹配;_(下劃線):與單個字符匹配。系統中的條件判斷往往包含多個條件,這時就需要使用邏輯運算符NOT、AND、OR(用于多條件的邏輯連接),謂詞ALL以及保留字DISTINCT等等。做為SELECT語句還有很多的使用方法,這里就不再敘述。2.3.3 SQL數據更新
使用數據庫的目的是為了有效地管理數據,而數據的插入、刪除和修改則是必不可少的一個功能。在本系統中就大量地使用了數據插入、刪除和修改這三種操作,現做一個簡單地介紹。●數據插入
往數據庫的基本表中插入數據使用的是INSERT語句,其方式有兩種:一種是元組值的插入,另一種是查詢結果的插入。在本系統中使用的是前一種方式,其句法如下:
INSERT INTO 基本表名(列表名)VALUES(元組值)●數據刪除
往數據庫的基本表中刪除數據使用的是DELETE語句,其句法如下: DELETE FROM 基本表名 [WHERE 條件表達式] 在 些作一點說明,刪除語句實際上是“SELECT * FROM 基本表名 [WHERE 條件表達式]”和DELETE操作的結合,每找到一個元組,就把它刪除。此外,DELETE語句只能從一個基本表中刪除元組,WHERE子句中條件可以嵌 套,也可以是來自幾個基本表的復合條件。●數據修改
當需要修改基本表中元組的某些列值時,可以用UPDATE語句實現,其句法如下: UPDATE基本表名
SET列名=值表達式[,列名=值表達式?] [WHERE條件表達式] 在Delphi 中使用SQL語句是很方便的,一般來說,都是通過TQuery組件來使用SQL語言的。有一點要進行說明,雖然通過TQuery組件來使用SQL語言很方 便,但考慮到自己對不同組件的理解程度、個人習慣以及其它各個方面,在本系統中我采用的是ADO組件來對數據庫進行操作。最簡單的方法比如在 TADOQuery組件的SQL屬性中就可以鍵入SQL語句,至于詳細的使用方法在后面進行介紹。
圖書倉庫管理系統的設計(3)第三章 數據庫開發工具 §3.1 Delphi 6.0 簡介
Delphi類可以粗略地分成兩部分:一部分是組件 類,這些組件類通常以某種方式出現在組件面板上,當用戶從組件面板上點取一個類的圖標后,在程序中就自動生成了該類的對象(非可視組件除外);另一部分是 功能類,這此功能類的對象通常出現在程序代碼中,起著不可代替的作用,但是這些功能類在組件面板上是找不到的。在Delphi中,每一個類的祖先都是 Tobject類,整個類的層次結構就像一棵倒掛的樹,在最頂層的樹根即為Tobject類。這樣,按照面向對象編程的基本思想,就使得用戶可用 Tobject類這個類型代替任何其它類的數據類型。實際上在Delphi的類庫中,Tobject類派生出了為數相當眾多的子類,它們形成了一個龐大的 體系,通常情況下,如果不自行開發組件,就不必了解整個類的體系結構,只用到類層次樹的葉結點就足夠了。
凡是做過程序開發的人都知道從來沒有單純 的數據應用程序,也就是說,數據庫應用程序必須和用戶界面(可以是圖形界面,也可以是命令接口)元素相結合,只講界面或只講數據庫本身都構不成數據庫應用 程序,因而用Delphi 6.0開發數據庫應用程序就隱含著界面開發。Delphi6中的VCL組件可用圖3-1來說明。組件在Delphi程序的開發中是最顯眼的角色。大家知 道,在編寫程序時一般都開始于在組件面板上選擇組件并定義組件間的相互作用。但也有一些組件不在組件面板上,例如Tform和Tapplication(典型的非可視組件)。組件是Tcomponents派生出來的子類,可以流的形式存放在DFM文件中,具有事件和Publish屬性。
窗口組件類是窗口化的可視化組件類,在Delphi的類庫中占有最大的份額。在實際編程中,窗口組件類的對象都有句柄,可以接受輸入焦點和包含其它組件。圖 形組件與窗口組件并列,是另一大類組件。圖形組件不是基于窗口的,因而不能有窗口句柄,不能接受輸入焦點和包含其它組件。從圖8-43中可以看出,圖形組 件的基類是TgraphicControl,在實際編程中,它們必須寄生于它們的宿主——窗口組件類的對象,由它們的擁有者負責其顯示,而且它們還能觸發 一些和鼠標活動相關的事件。圖形控件最典型的例子是Tlabel和TspeedButton。由此可以看出圖形組件的功能很弱,有讀者會問圖形組件的用處 何在呢?其實使用圖形組件的最大好處在于節省資源,正是因為它們的功能較弱,所以使用的系統資源就要少。在一個應用程序中,如果能在不影響其功能的前提下 合理大量地使用圖形組件,將會大減少程序對系統資源的消耗。非可視組件是與可視組件相并列的另一類組件,非可視組件在程序運行中是不可見的(除各種對話框組件之外,事實上有人認為對話框組件不能歸入非可視組件,應該是另一種介于可視與非可視之間的組件)。§3.2 Delphi 6.0 控件
用Delphi6開發數據庫應用,重點是和各種數據庫組件打交道,當然也要使用其它的一些組件,現在就我在系統設計中所使用的重要組件給與簡單介紹。3.2.1 ADO數據訪問組件
ADO 數據對象(Active Data Objects)實際是一種提供訪問各種數據類型的鏈接機制。ADO設計為一種極簡單的格式,通過ODBC的方法同數據庫接口中,可以使用任何一種 ODBC數據源,即不止適合于SQL Server、Oracle、Access等數據庫應用程序,也適合于Excel表格、文本文件、圖形文件和無格式的數據文件。ADO是基于OLE-DB 之上的技術,因此ADO通過其內部的屬性和方法提供統一的數據訪問接口方法。ADO使您的客戶端應用程序能夠通過OLE DB提供訪問和操作在數據庫服務器中的數據。ADO支持用于建立C/S和Web的應用程序的主要功能。其主要優點是易于使用、高速度、低內存支出和占用磁 盤空間較少。ADO同時具有遠程數據服務(RDS)功能,通過RDS可以在一次往返過程中實現將數據從服務器移動到客戶端應用程序和Web頁、在客戶端對 數據進行處然后將更新結果返回服務器的操作。
Delphi 6.0繼續對Microsoft的ADO訪問能力的支持。這種能力是通過一組新組件實現的,這些組件是在企業版的ADO組件頁中,在組件面版的ADO頁上 可以找到這些組件。利用在前面章節提到的TdataSet抽象類,ADO組件可以不通過BDE而直接實現ADO連接。這意味著只需要很少的代碼就可以實現 該連接并且性能得到提高。
利用ADO數據訪問組件,可以只使用ADO結構與數據庫取得聯系并對其中的數據進行操作,而在這些過程中完全不需要使用 BDE。大多數的ADO連接和數據集組件都是與基于BDE的連接和數據集組件相類似的。TADOConnection組件與基于BDE的應用程序中的 Tdatabase組件類似。TADOTable與Ttable,TADOQuery與Tquery,以及TADOStoreProc和 TstoredProc之間都具有這種類似的對應關系。使用這些ADO組件的方式與我們常使用的數據訪問組件(基于BDE)都有許多相同之處。TTADODataSet沒有直接的BDE對應組件,但它提供了許多與Ttable和Tquery相同的功能。同樣,TADOCommand也沒有相對應 的BDE組件,它是在Delphi/ADO環境中完成特定功能的組件。Delphi 6.0通過ADO數據集訪問組件,可以不借助BDE數據引擎而是通過微軟的OLEDB來訪問更為廣泛的數據庫中的數據。ADO數據集訪問組件與常用的數據 訪問組件是并列的關系。在系統中我主要使用的是ADOTablet和ADOQuery兩個組件。3.2.2 數據控制類DataControl 數 據控制類負責數據庫數據的顯示,并把用戶對數據的修改傳回。這里的絕大多數組件,如DBText, DBEdit, DBMemo, DBImage, DBListBox, DBComboBox, DBCheckBox, DBRadioGroup, DBLookupListBox, DBLookupCombox, DBCtrGrid的功能和對應的非數據感知組件相同,如TEdit框,TRadioGroups單選按鈕組等,只不過在顯示數據庫數據時要用而已。
在系統中主要使用數據網格控件DBGrid和數據庫導航器控件DBNavigator。3.2.3 數據訪問類DataAccess 數 據庫應用系統中數據訪問是一個首要問題,包括單用戶和 C/S系統,都必須聯系一些數據庫和數據表文件。Delphi 6 提供了專門用于數據訪問的基類控件。主要包括數據源控件DataSource、客戶數據集控件ClientDataSet、數據集提供器控件 DataSetProvider等等。
Tdatabase:當一個基于BDE的數據庫應用程序需要一個永久數據庫連接時,需要定制向一個數據庫服 務器的連接時,需要事務控制和特殊的數據庫別名時就得用到Tdatabase對象。特別是當連接到一個遠程的SQL數據庫服務器時,如果要利用BDE進行 數據庫事務處理,那么,TDatabase對象的威力就體現出來了。在一個應用程序中為每一個數據庫連接顯示的聲明Tdatabase對象要根據需要而 定,不是必需的。對一個數據庫連接,如果沒有顯示的聲明并實例化TDatabase對象,系統就會產生一個帶有默認屬性的TDatabase對象。
TdataSource 對象用于在DataSet對象(包括Tquery,TstoredProc,Ttable等)和數據感知組件之間提供一個連接的紐帶,以便在窗體上顯示數 據庫中的數據,在數據庫中導航定位與編輯數據集中的數據。如果一個DataSet對象中的數據想在數據感知組件中顯示和修改,它就必須和 TdataSource對象相聯系。同樣,一個數據感知組件如果想和數據源相聯系以便顯示和操縱數據,就必須以TDataSource對象為中介。
用Delphi6作數據庫應用開發概括來說如下:先利用數據存取組件和實際的數據庫建立連接,并用Tsession對象和Tdatabase對象管理這些連接。然后以Tdatasource對象為中介,用數據感知組件向用戶顯示數據庫的內容并接受用戶的查詢和修改等操作。
3.2.4 SQL語言在Delphi中的應用
在Delphi 中使用SQL語言非常方便,一般來說,都是通過Tquery組件來使用SQL語言的。可以在TQuery組件的SQL屬性中設置SQL語句。設計程序時,在該組件的屬性對話框中選擇SQL屬性,單擊帶省略號的按鈕,就可以打開String List Editor對話框,然后我們就可以在對話框中添加SQL語句。還可以使用Delphi的SQL Builder來自動生成SQL語句,這樣可以避免手工編寫SQL而可能造成的語法錯誤。
靜態SQL語句在程序設計時便已固定下來,它不包含任何參數和變量。
動態SQL語句,也被稱作參數化的語句,在其中間包含著表示字段名或表名的參數,例如下面的語句是一條動態SQL語句:
Select * From Students Where StudentCode =: StudentCode;其中的變量StudentCode便是一個參數變量,它由一個冒號引導,在程序運行過程中,必須要為該參數賦值,該條SQL語句才能正確執行,每次運行應用程序時可以為該參數變量賦予不同的值。為參數賦值有三種方法: ①根據參數在SQL語句中出現的順序,設置TQuery部件的Params屬性值為參數賦值。
②直接根據SQL語句中各參數的名字,調用ParamByName方法來為各參數賦值。③將TQuery部件的DataSource屬性設置為另一個數據源,這樣將另一個數據源中與當前TQuery部件的SQL語句中的參數名相匹配的字段值賦給其對應的參數。利用這種方法也能實現所謂的連接查詢,創建主要—明細型數據庫應用。
在程序運行過程中,要想設置TQuery部件的SQL屬性,必須首先調用Close方法,關閉TQuery部件,然后再調用Clear方法清除SQL屬性中現存的SQL命令語句,最后再調用Add方法為SQL屬性設置新的SQL命令語句。例如: Query1.Close {關閉Query1)Query1.SQL.Clear {清除SQL屬性中的SQL命令語句} Query1.SQL.Add(‘Select * From Students‘);Query1.SQL.Add(‘ Where Name =“Lucy” ‘);
在 為TQuery部件設置SQL屬性時調用Close方法總是很安全的,如果TQuery部件已經被關閉了,調用Close方法時不會產生任何影響。在應用 程序中為SQL屬性設置新的SQL 命令語句時,必須要調用Clear方法以清除SQL屬性中現存的SQL命令語句,如果不調用Clear方法,便調用Add方法向SQL屬性中設置SQL命 令語句,那么新設置的SQL命令語句會追加在現存SQL命令語句后面,在程序運行時常常會出現出乎意料的查詢結果甚至程序無法運行下去。在這里 要特別注意的,一般情況下TQuery部件的SQL屬性只能包含一條完整的SQL語句,它不允許被設置成多條SQL語句。當然有些數據庫服務器也支持在 TQuery部件的SQL屬性中設置多條SQL語句,只要數據庫服務器允許這樣,我們在編程時可以為 SQL 屬性設置多條SQL語句。
在為TQuery部件設置完SQL屬性的屬性值之后,也即編寫好適當的SQL程序之后,可以有多種方式來執行SQL程序。
在 設計過程中,設置完TQuery部件的SQL屬性之后將其Active屬性的值置為True,這樣便可以執行SQL屬性中的SQL程序,如果應用中有與TQuery部件相連的數據瀏覽部件(如TDDGrid TDBEdit等)那么在這些數據瀏覽部件中會顯示SQL程序的執行結果。
在應用程序運行過程中,通過程序調用TQuery部件的Open方法或 ExecSQL 方法可以執行其SQL屬性中的SQL程序。Open方法和ExecSQL方法是不一樣的。Open方法只能用來執行SQL語言的查詢語句(Select命 令),并返回一個查詢結果集,而ExecSQL方法還可以用來執行其它常用的SQL語句(如INSERT, UPDATE, DELETE等命令),例如:
Query1.Open(這樣會返回一個查詢結果集)如果調用Open方法,而沒有查詢結果時,會出錯。此時應該調用ExecSQL 方法來代替Open方法。如:
Query1.ExecSQL(沒有返回結果)當 然在設計應用程序時,程序設計人員是無法確定TQuery部件中的SQL 語句是否會返回一個查詢結果的。對于這種情況應當用Try?Except模塊來設計程序。在 Try 部分調用Open方法,而在Except部分調用ExceSQL方法,這樣才能保證程序的正確運行。
Delphi中用ADOQuery來使用 SQL語句同樣十分方便。在ADOQuery組件中首先通過ConnectionString屬性值來聯接數據源,然后就通過雙擊SQL?屬性值來寫入 SQL語句。在Delphi中調用數據庫,就可以調用ADOQuery組件,通過修改其中的SQL?屬性中的SQL語句來實現對數據庫的各項操作。
值 得注意的是,ADOQuery組件只有在激活的情況下才可以被正確地使用,這樣就提出了一個問題,也就是說,在每次修改ADOQuery組件的SQL?屬 性時都必須先行進行關閉,待清除掉SQL?中所有的SQL語句后才可以添加新的SQL語句。而且,在每一次修改完成以后,還應該記得重新將 ADOQuery激活。其它的使用方法與TTQuery有許多的相似之處。§3.3 Access 簡介
建立一個數據庫我們有多種選擇,現在市場上有各種各樣的數據庫,而且每一種數據庫都有其自身的特點,不能說哪一種更好,只能在其中尋找一種能更好地適應系統需求、更好地滿足用戶的要求以 及適應開發人員的習慣。在本系統中,做為圖書倉庫管理系統是一個比較小的應用系統,它所產生和處理的數據量也比較小。因此,沒有必要使用像SQL Server和Oracle這樣的大型數據庫。我首先想到的數據庫是Borland公司的Paradox數據庫。另外,Microsoft Office中的Access數據庫在計算機上的應用比較普及,是開發小型數據庫系統的比較理想的選擇,所以,在本系統中我選擇了Access數據庫。
Access 做為一個數據庫管理系統,它被集成在Microsoft Office中。Access數據庫處理的基本結構,采取關系型數據庫模式。與其他的數據庫系統相比,Access更加簡單易學,一個普通的計算機用戶可 以很快地掌握它。Access 2000的功能十分強大,利用它可以方便地實現對信息保存、維護、查詢、統計、打印、交流、發布,而且它可以十分方便地與Office其他組件交流數據,這些功能對一個一般用戶而言已經足夠了。
圖書倉庫管理系統的設計(4)第四章 系統總體設計
軟件系統的總體設計大約要經歷可行性分析和項目開發計劃,需求分析,概要設計,詳細設計,編碼,測試以及 維護等七個階段。可行性分析和項目開發計劃在前面已經敘述,下面所要做的是進行軟件需求分析,概要設計和詳細設計。編碼過程將在下一節論述,而測試和維護 過程不在本文敘及。§4.1 系統需求分析
在經過前一階段的分析之后,我確定了我的開發課題為圖書倉庫管理。現在所要做的是要準確定義系統必須做什么以及系統必須具備的功能。
軟 件需求分析中我采用結構化分析方法(Structured Analysis,簡稱SA),SA是面向數據流進行需求分析的方法,像所有的軟件分析方法(如面向對象分析方法、IDEF方法等等)一樣,SA也是一種 建模活動,它使用簡單易讀的符號,根據軟件內部數據傳遞、變換的關系,自頂向下逐層分解,描繪滿足功能要求的軟件模型。
在系統中我采用數據流圖(DFD)這種半形式化的描述方式表達需求。它是一種功能模型,以圖形的方式描繪數據在系統中流動和處理的過程,只反映系統必須完成的邏輯功能。它有四種基本圖形符號: ◆ →:箭頭,表示數據流; ◆ 〇:圓或橢圓,表示加工; ◆ ═:雙杠,表示數據存儲;
◆ □:方框,表示數據的源點或終點。
為了表達較為復雜問題的數據處理過程,用一張數據流圖是不夠的,要按照問題的層次結構進行逐步分解,并以一套分層的數據流圖反映這種結構關系。在這里我一共使用了三層數據流圖,即頂層圖,0層圖和1層圖(也是底層圖)。在多層數據流圖中,頂層流圖僅包含一個加工,它代表被開發系統,它的輸入流是該系統的輸入數據了,輸出流是該系統的輸出數據;底層流圖是指其加工不需要再做分解的數據流圖,中間層流圖表示對其上層父圖的細化,它的每一步加工可能繼續細化成子圖。
經過對系統的分析首先得到系統的頂層DFD,如下: 一步細化得到系統的0層DFD,如下:
再進一步細化每一個數據加工功能,得到系統的1層DFD圖。
在這里只給出有關入庫管理和出庫管理的1層數據流圖,它們是系統的關鍵部分,也是主要的部分。通過以上對數據流圖的分析之后,我們已大體地了解了系統的功能和目標,接下來所要做的就是系統功能模塊的劃分和數據庫的設計,也就是系統的概要設計。§4.2 系統概要設計
在軟件需求分析階段,搞清楚了軟件“做什么”的問題,形成了目標系統的邏輯模型。現在我們所要做的就是要把軟件“做什么”的邏輯模型變換為“怎么做”的物理模型,即著手實現軟件的需求。首先,我們需要描述的是系統的總的體系結構。
4.2.1 系統結構設計
系統的概要設計中最重要的就是系統的模塊化。模塊化是指解決一個復雜問題時自項向下逐層把軟件系統劃分成若干個模塊的過程。每個模塊完成一個特定的功能,所有的模塊按某種方法組織起來,成為一個整體,完成整個系統所要求的功能。
將系統劃分為多個模塊是為了降低軟件系統的復雜性,提高可讀性、可維護性,但模塊的劃分不能是任意的,應盡量保持其獨立性。也就是說,每個模塊只完成系統 要求的獨立的子功能,并且與其他模塊的聯系最少且接口簡單,即盡量做到高內聚低耦合,提高模塊的獨立性,為設計高質量的軟件結構奠定基礎。在系統 的概要設計中我采用結構化設計(Structure Design,簡稱SD),SD以需求分析階段產生的數據流圖DFD為基礎,按一定的步驟映射成軟件結構。我首先將整個系統化分為幾個小問題,小模塊,在 系統中,我設計了用戶管理、庫存管理、入庫管理、出庫管理、員工管理和供應商管理6個小模塊。然后,進一步細分模塊,添加細節。比如,用戶管理我又將其分 為用戶注冊、用戶注銷、密碼修改;庫存管理分為庫存記錄查詢、庫存記錄修改、庫存記錄打印等等。以下就是系統的結構圖:(在這里為了表達方便我將結構圖分開來表達。)
在得到系統的第一層功能模塊圖后,經過進一步地細化,得一系統的子功能模塊圖:
4.2.2 數據庫設計
在信息世界中,信息從客觀事物出發流經數據庫,通過決策機構最后又回到客觀世界,信息的這一循環經歷了三個領域: 信息世界,數據世界,現實世界。現實世界的事物反映到人的頭腦中,人的大腦對它有個認識過程,經過分析(選擇、命名、分類等)進入信息世界。這些信息再進 一步加工、編碼,然后進數據世界,而軟件系統的開發工作需要考慮這兩個方面的問題,也就是要考慮系統開發所需要的數據,以及如何對這些數據進行操作。這兩 個問題貫穿了整個軟件系統的開發過程,這也就是數據庫的設計問題,軟件設計的一個核心。4.2.2.1 ER圖設計
在系統設計的開始,我首先考慮的是如何用數據模型來數據庫的結構與語義,以對現實世界進行抽象。目前廣泛使用的數據模型可分為兩種類型,一種是獨立于計算機系統的“概念數據 模型”,如“實體聯系模型”;另一種是直接面向數據庫邏輯結構的“結構數據模型”。在本系統中我采用“實體聯系模型”(ER模型)來描述數據庫的結構與語 義,以對現實世界進行第一次抽象。ER模型直接從現實世界抽象出實體類型及實體間聯系,然后用ER圖來表示數據模型。它有兩個明顯的優點:接近于人的思 維,容易理解;與計算機無關,用戶容易接受。但ER模型只能說明實體間語義的聯系,不能進一步說明詳細的數據結構,它只是數據庫設計的第一步。
ER圖是直觀表示概念模型的工具,它有四個基本成分: ◆ 矩形框,表示實體類型(考慮問題的對象)。◆ 菱形框,表示聯系類型(實體間的聯系)。
◆ 橢圓形框,表示實體類型和聯系類型的屬性。對于關鍵碼的屬性,在屬性名下劃一橫線。
◆直線,聯系類型與其涉及的實體類型之間以直線連接。
本系統為圖書倉庫管理,主要管理圖書的入庫、出庫以及庫存等事項。倉庫根據需要可以查詢圖書供應商的信息,同時還需要了解在入庫和出庫中員工的參與情況。依據倉庫管理的實際情況,考慮了多方面的因素以后,確定系統的ER圖如下:
(為了表達的方便,在這里我沒有在一張圖上表達出所有的關系,而是用一張總體ER圖,和幾張實體屬性關系圖來表達數據庫的結構。)
在 該數據庫中,我設計了三個實體,分別是庫存、員工和供應商以及兩個聯系類型入庫和出庫。在本系統中庫存是核心,也是基本,沒有了庫存其它的也就沒有什么意 義了。員工記錄的添加是考慮到責任問題,也就是說,在倉庫管理的實際運用中,出現了責任不清的現象,特別是由于倉庫的進出圖書數量都比較大時產生了一系列 問題,所以在設計數據庫時,我特別考慮到這一點,加入了員工記錄這一實體。供應商信息的添加主要出于對圖書來源問題的思考。通過添加供應商信息可以比較清 楚地了解圖書的進貨渠道,從圖書的質量到供應商的信譽都可以進行了解,同時可以為以后的圖書進購提供一定有用的信息。
入庫聯系類型將庫存信息、供應商信息和員工信息聯系在一起,可以方便地實現三個實體之間的聯接,而出庫聯系類型則將庫存信息和員工信息較好地聯接起,同時這兩個聯系類型又都具有各自特有的屬性。下面就是各實體及聯系類型的屬性圖:(帶#號的屬性為關鍵字段)4.2.2.2 數據庫表格設計
在完成系統的ER圖之后,需要將ER模型轉化為關系模型,也就是說,要設計出數據庫所需要的表格。在這里,我選用的是關系數據庫。因為關系數據庫中的二維表格可以很清楚地描述數據之間的聯系。
在這里不得不提到一個概念——范式。其實在上一節的ER圖設計中,已經運用了范式的思想,不僅如此,在數據庫的表格設計中更離不開范式的思想,它是數據庫設計的基礎,如果不注意這個問題將會導致一系列問題的出現。
我 在系統中定義的表格都嚴格地按照范式的思想和要求去完成,數據庫中的所有表格都達到了三范式的要求。根據系統ER圖,針對本系統的特點,在對所搜集的數據 進行規范化之后,定義了如下六張表格,分別是庫存信息表,入庫信息表,出庫信息表,員工信息表,供應商信息表和密碼信息表。通過對這六張表格的操作可以較 好地完成系統設計的各項功能,六張表格之間有著不同程度的聯系。(說明:在以下數據表中,K代表主鍵,#代表外鍵,字段值不為空。)BookRecord 表(庫存信息表)
字段名稱 數據類型 說明 K BookID 數字 圖書編號 BookName 文本 圖書名 Author 文本 作者
Publisher 文本 出版社
PubDate 日期/時間 出版日期 Price 貨幣 價格
BookType 文本 圖書類型 Number1 數字 庫存數量 Addation 文本 備注 圖4.13 庫存信息表
庫存信息表主要用于記錄倉庫中現存放的所有圖書的詳細信息,包括圖書編號、書名、作者、出版社、圖書類型等有關圖書的各類信息,它即是該數據庫的主表,也是系統主界面的主要內容。
在 該表中圖書編號是主鍵,它按圖書入庫的先后次序來編寫,每當有圖書入庫,系統自動給出圖書編號,這樣我們按圖書編號來查找圖書是比較方便的。考慮到編號比 較難于記憶,所以使用了出版社和圖書類型兩個字段,在系統中我提供了出版社和圖書類型的分類查找,而且全部采用自動生成,每當系統中有新的出版社類型和圖 書類型,彈出菜單會自動添中新類型,這樣就可以比較方便地實現按出版社和按圖書類型查找。此外,庫存數量也是一個比較關鍵的字段,該字段是在系統初始化時 就給定的,每當有圖書入庫或出庫操作,系統就會自動修改圖書的庫存數量,以保持數據的一致性。做為備注有一點說明,我的數據庫中備注的數據類型是文本,而 不是備注類型,主要考慮到該字段的長度并不大,而且在Delphi中文本數據類型的處理也比較方便一點。Employee 表(員工信息表)字段名稱 數據類型 說明 K EmployeeID 數字 員工編號 EmployeeName 文本 員工姓名 Sex 文本 性別
BornDate 日期/時間 出生日期 Grade 文本 職稱
WorkDate 日期/時間 工作日期 Telephone 文本 聯系電話 Address 文本 聯系地址
圖4.14 員工信息表
員 工信息表主要用于記錄有關員工的各類信息,包括姓名、職稱、出生日期、聯系電話、聯系地址等。它主要用來為系統提供員工的有關信息,因為在系統中,入庫和 出庫操作均與員工有著一定的聯系,在查詢入庫信息和出庫信息時,有時需要查找有關此項記錄有關的員工信息,在系統中我是通過入庫記錄與員工記錄(出庫記錄 和員工記錄)之間的聯接查詢來完成的。另外,作為一個倉庫也有必要了解其所屬員工的一些基本情況,以便查詢。Shopkeeper 表(供應商信息表)
字段名稱 數據類型 說明
K ShopkeeperID 數字 供應商編號 ShopkeeperName 文本 供應商姓名 Address 文本 地址 PostNo 數字 郵編
OfficePhone 文本 辦公電話 HomePhone 文本 住宅電話 Email 文本 E-mail PayType 文本 付款方式
圖4.15 供應商信息表
供 應商信息表主要用于記錄有關供應商的各類信息,包括姓名、地址、電話、付款方式等。它主要用來為系統提供供應商的有關信息,在系統中入庫記錄是與供應商記 錄相聯系的,通過入庫記錄可以查找相關的供應商信息。在供應商信息中,考慮當實際情況,我特別加入了Email和付款方式這兩個字段,因為在當今信息世界 中,多種多樣的通訊方式和多種多樣的付款方式是必然的,是數據庫中必須與以記錄。
InRecord 表(入庫信息表)
字段名稱 數據類型 說明 K InID 數字 入庫編號 # BookID 數字 圖書編號
# EmployeeID 數字 員工編號
# ShopkeeperID 數字 供應商編號 Number 數字 入庫數量
BuyDate 日期/時間 入庫日期
圖4.16 入庫信息表 OutRecord 表(出庫信息表)
字段名稱 數據類型 說明 K OutID 數字 出庫編號 # BookID 數字 圖書編號
# EmployeeID 數字 員工編號 Number2 數字 出庫數量
OutDate 日期/時間 出庫日期
圖4.17 出庫信息表
入 庫信息表主要用于記錄有關入庫的詳細信息,包括入庫數量、入庫日期以及圖書、員工、供應商三方的編號,以便查詢。出庫信息表主要用于記錄有關出庫的詳細信 息,包括出庫數量、出庫日期以及圖書、員工的編號。出庫信息表和入庫信息表一樣,其實它們都屬于聯系類型,系統通過這兩個表可以聯接上其它的表為用戶提供 多種條件的聯接查詢。值得提出的一點是入庫記錄和出庫記錄的添加不僅僅是單表操作,由于它們都與庫存記錄相聯系,所以,無論您是添中入庫記錄還是添加出庫 記錄,都必須同時修改庫存記錄,以保持數據的一致性,否則將引發系統出錯而這些我都讓其在系統中自動完成。無論您是添加入庫記錄,還是添加出庫記錄,系統 都將自動修改庫存中圖書的數量,而且,在您出庫的數量大于庫存數量時,系統還會自動提示錯誤,這樣就可以防止一定錯誤的發生。
在入庫信息表和出庫 信息表中我還定義了幾個外鍵,它提供了一種表示幾個關系聯系的方法。比如,系統中通過在入庫信息表中定義的外鍵 BookID、EmployeeID和ShopkeeperID可以將庫存信息表、員工信息表和供應商信息表聯系在一起,從而方便地實現聯接查詢,而且,引入外鍵的定義是實體完整性約束的一個主要方面。Key 表(密碼信息表)
字段名稱 數據類型 說明 K KeyName 文本 用戶姓名 KeyNo 文本 用戶密碼 圖4.18 密碼信息表
密碼信息表主要用于記錄所有的用戶名和用戶密碼。它是在用戶登陸時用來確定用戶和密碼的正確性,以防止非法用戶登陸。
通過以上設計已經完成了系統的概要設計,當我們有了系統的功能模塊圖和數據庫之后,就需要著手去實現每一個模塊,為每一個功能設計程序流程圖,這也就是系統的詳細設計。§4.3 系統詳細設計
在前面的概要設計中,已將系統劃分為多個模塊,并將它們按照一定的原則組裝起來,同時確定了每個功能及模塊之間的外部接口。現在所要做的就是確定每個模塊具體執行過程,也可以說是“過程設計”。
在 處理過程設計時我采用的是結構化程序設計(簡稱SP)方法。需要指出的是系統的詳細設計并不是指具體的編程序,而是將概要設計階段產生的系統功能模塊圖細 化成很容易產生程序的圖紙。因此詳細設計的結果基本決定了最終程序的質量。為軟件的質量,延長軟件的生存期,軟件的可測試性、可維護性提供重要的保障。詳 細設計的目標不僅是邏輯上正確地實現每個模塊的功能,還應使設計出的處理過程清晰易讀。
由前一階段產生的系統功能模塊圖,我為系統的主要部分設計 了如下程序流程圖:通過以上步驟,基本上完成了對整個系統的總體設計,接下來所要做的就是軟件的編碼工作。系統總體設計的好壞直接影響著下一步工作,只有 在這一階段設計出好的模塊圖和程序流程圖,才能更有利于編碼,產生好的軟件系統。
圖書倉庫管理系統的設計(5)第五章 系統應用程序設計
§5.1 系統窗體模塊組成 §5.2 數據模塊窗體的設置
在編寫數據庫應用程 序時,經常要遇到這樣的情況,即好多組件、窗體同時訪問相同的數據源,如果為每一個組件或者窗體都設置一個數據源將是十分耗時的工件,而且要保證這些數據 源的確是相同的也需花一番功夫。那么,能不能將這些數據源集中管理,最好是做成一個統一的模塊,需要時就將該模塊引入而不必直接操作數據源本身呢?數據模 塊(DataModule)是解決這個問題最好的答案。簡單說來,數據模塊是用來集中管理數據源的一個窗體,該窗體可被需要的地方隨時引入。
圖5.2 給出了本程序的數據模塊(datamoduleform)窗體圖,除報表窗體外所有的數據存取組件和數據源組件都在此數據模塊中進行了定義。值得一提的 是,設置了數據庫Database組件,該組件引入了系統所需的唯一的數據庫tsxs,Database組件的DatabaseName屬性設置為 tsckgl。tsxs數據庫已在ODBC配置程序中進行了設置。其他的數據存取組件都是基于此數據庫組件創建的,這樣做的好處是,當數據庫的別名或者其 他信息改變之后,只需修改Tdatabase組件的AliasName屬性即可。
另外,在本系統的數據模塊窗體圖中,我大多采用的 AODQuery組件而沒有采用BDE組,這主要是基于對ADO組件的了解。在Delphi的學習中我對ADO組件了解的更加清楚,使用也較BDE更為熟 練,而且,ADO組件的功能也較BDE更為強大,所以在這里大多采用ADO組件來進行數據庫聯接。同時我也使用了BDE組件中的Table,因為在某些時 候BDE有著其自身特有的優越性。主窗體功能模塊的實現 file://主窗體程序代碼
public file://在程序的起始部分,定義快捷按鈕點擊事件 Procedure Popup1Handler(Sender:Tobject);Procedure Popup2Handler(Sender:TObject);********************************************************************** procedure Tmainform.Popup1Handler(Sender: TObject);begin file://快捷按鈕1(點“按出版社分類”按鈕產生)的點擊事件 with datamoduleform.MainQuery do begin file://打開數據模塊窗體的MainQuery,對BookRecord表進行操作 close;file://關閉MainQuery SQL.Clear;file://清除SQL屬性中的SQL命令語句 SQL.Add(‘select * from BookRecord where Publisher=:Pub‘);file://添加新的SQL語句
Parameters.ParamByName(‘Pub‘).Value:=(Sender as TMenuItem).Caption;open;file://重新打開MainQuery end;end;********************************************************************** procedure Tmainform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3,s4,s5 :String;file://設立5個變量以方便實現模糊查詢 begin file://主窗口庫存查詢按鈕事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);
SQL.Add(‘where BookID Like :BookID and BookName Like :Name and Author Like :Author and Publisher Like :pub and BookType Like :BookType‘);file://使用Like語句來實現模糊查詢 if Edit1.Text<>‘‘ then s1:=‘%‘+Edit1.Text+‘%‘ else s1:=‘%‘;Parameters.ParamByName(‘BookID‘).Value:=s1;file://給變量s1賦值 if Edit2.Text<>‘‘ then s2:=‘%‘+Edit2.Text+‘%‘ else s2:=‘%‘;Parameters.ParamByName(‘Name‘).Value:=s2;file://給變量s2賦值 if Edit3.Text<>‘‘ then s3:=‘%‘+Edit3.Text+‘%‘ else s3:=‘%‘;Parameters.ParamByName(‘Author‘).Value:=s3;file://給變量s2賦值 if Edit4.Text<>‘‘ then s4:=‘%‘+Edit4.Text+‘%‘ else s4:=‘%‘;Parameters.ParamByName(‘Pub‘).Value:=s4;file://給變量s2賦值
if Edit5.Text <>‘‘ then s5:=‘%‘+Edit5.Text+‘%‘ else s5:=‘%‘;
Parameters.ParamByName(‘BookType‘).Value:=s5;file://給變量s2賦值 open;if FieldValues[‘BookID‘]=NULL file://判斷是否找到記錄 then begin Messagedlg(‘沒有找到你所需要的記錄!‘,mtInformation,[mbOK],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit4.Text:=‘‘;Edit5.Text:=‘‘;close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);file://這里相當于一個刷新功能 open;end;end;end;********************************************************************** procedure Tmainform.SpeedButton3Click(Sender: TObject);begin file://庫存表刷新按鈕事件 with datamoduleform.MainQuery do begin close;SQL.Clear;SQL.Add(‘select * from BookRecord‘);open;end;end;********************************************************************** procedure Tmainform.SpeedButton11Click(Sender: TObject);var PopupItem:TMenuItem;begin file://自動生成快捷按鈕1的內容 with datamoduleform.BookQuery do begin file://從數據庫中選擇出版社類型 close;SQL.Clear;SQL.Add(‘select distinct Publisher from BookRecord‘);open;PopupMenu1:=TPopupMenu.Create(Self);file://自動生成快捷菜單 PopupMenu1.AutoHotkeys:=maManual;file://自定義熱鍵 while Not Eof do begin file://根據出版社內容生成菜單子項 PopupItem:=TMenuItem.Create(Self);PopupItem.Caption:=FieldByName(‘Publisher‘).AsString;PopupMenu1.Items.Add(PopupItem);PopupItem.onClick:=Popup1Handler;file://確定菜單子項的點擊事件 Next;end;end;PopupMenu1.Popup(384,67);file://在指定位置顯示快捷菜單1 end;********************************************************************** procedure Tmainform.FormActivate(Sender: TObject);begin file://系統初始化,在進入mainform時自動添加數據源 mainform.DBGrid1.DataSource:=datamoduleform.MainSource;mainform.DBNavigator1.DataSource:=datamoduleform.MainSource;mainform.DBGrid2.DataSource:=datamoduleform.EmpSource;mainform.DBNavigator2.DataSource:=datamoduleform.EmpSource;mainform.DBGrid3.DataSource:=datamoduleform.ShopSource;mainform.DBNavigator3.DataSource:=datamoduleform.ShopSource;mainform.DBGrid4.DataSource:=datamoduleform.InSource;mainform.DBNavigator4.DataSource:=datamoduleform.InSource;mainform.DBGrid5.DataSource:=datamoduleform.OutSource;mainform.DBNavigator5.DataSource:=datamoduleform.OutSource;end;********************************************************************** procedure Tmainform.FormCreate(Sender: TObject);begin file://系統初始化,定義界面大小,以適應不同分辯率 Width:=800;Height:=600;end;********************************************************************** procedure Tmainform.Timer1Timer(Sender: TObject);begin file://在狀態欄顯示時間
StatusBar1.Panels[2].Text:=DateToStr(Date);StatusBar1.Panels[4].Text:=TimeToStr(Time);end;§5.4 入庫、出庫窗體模塊的實現
圖5.4 系統入庫管理窗體
圖5.5 系統出庫管理窗體
procedure Tinoutform.SpeedButton4Click(Sender: TObject);begin file://入庫管理查找按鈕事件
with datamoduleform.BookQuery do file://入庫查詢處理 begin close;SQL.Clear;SQL.Add(‘select * from BookRecord where BookID=:BookID‘);Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;open;if FieldValues[‘BookID‘]<>NULL then begin Edit1.Text:=‘‘;
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;Edit6.Text:=FieldValues[‘BookName‘];file://顯示圖書名
Edit6.ReadOnly:=true;Edit6.Color:=clMenu;file://設置顯示框不可更改屬性
Edit7.Text:=FieldValues[‘Author‘];
Edit7.ReadOnly:=true;Edit7.Color:=clMenu;Edit8.Text:=FieldValues[‘Publisher‘];Edit8.ReadOnly:=true;Edit8.Color:=clMenu;Edit9.Text:=FieldValues[‘PubDate‘];
Edit9.ReadOnly:=true;Edit9.Color:=clMenu;Edit10.Text:=FieldValues[‘Price‘];
Edit10.ReadOnly:=true;Edit10.Color:=clMenu;Edit11.Text:=FieldValues[‘BookType‘];
Edit11.ReadOnly:=true;Edit11.Color:=clMenu;Edit12.Text:=FieldValues[‘Number1‘];
Edit12.ReadOnly:=true;Edit12.Color:=clMenu;If FieldValues[‘Addation‘]<>NULL then Edit25.Text:=FieldValues[‘Addation‘]
else Edit25.Text:=‘‘;
Edit25.ReadOnly:=true;Edit25.Color:=clMenu;end else begin file://在沒有查找到的情況下,清空所有顯示框
Edit1.ReadOnly:=false;Edit1.Text:=‘‘;Edit1.Color:=clMenu;
Edit6.ReadOnly:=false;Edit6.Text:=‘‘;Edit6.Color:=clMenu;
Edit7.ReadOnly:=false;Edit7.Text:=‘‘;Edit7.Color:=clMenu;Edit8.ReadOnly:=false;Edit8.Text:=‘‘;Edit8.Color:=clMenu;
Edit9.ReadOnly:=false;Edit9.Text:=‘‘;Edit9.Color:=clMenu;
Edit10.ReadOnly:=false;Edit10.Text:=‘‘;Edit10.Color:=clMenu;
Edit11.ReadOnly:=false;Edit11.Text:=‘‘;Edit11.Color:=clMenu;Edit12.ReadOnly:=false;Edit12.Text:=‘‘;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=‘‘;Edit25.Color:=clMenu;
MessageDlg(‘沒有找到你所需要的記錄!‘,mtInformation,[mbOK],0);
Edit13.Text:=‘‘;Edit13.SetFocus;end;end;with datamoduleform.InQuery do file://自動入庫編號的獲取 begin close;SQL.Clear;SQL.Add(‘select * from InRecord where InID>=All(select InID from InRecord)‘);
open;file://找到入庫編號中最大的一個 Edit26.ReadOnly:=false;Edit26.Text:=FieldValues[‘InID‘]+1;file://最大的入庫編號加1形成新的入庫編號
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;file://設置編號的不可更改性 end;end;********************************************************************** procedure Tinoutform.SpeedButton1Click(Sender: TObject);var s:integer;begin file://入庫管理添加按鈕事件 if Edit1.Text<>NULL then MessageDlg(‘請輸入完整的入庫信息和圖書信息,然后單擊確定按鈕。‘,mtInformation,[mbok],0)else begin if(Edit2.Text=‘‘)or(Edit3.Text=‘‘)or(Edit4.Text=‘‘)or(Edit5.Text=‘‘)then begin MessageDlg(‘請輸入完整的入庫信息!‘,mtInformation,[mbok],0);Edit2.SetFocus;end else begin with datamoduleform.InQuery do file://將找到的圖書信息顯示 begin close;SQL.Clear;SQL.Add(‘insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)‘);file://向入庫信息表中插入記錄
Parameters.ParamByName(‘InID‘).Value:=Edit26.Text;file://向Edit框取值
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;
Parameters.ParamByName(‘EmpID‘).Value:=Edit2.Text;
Parameters.ParamByName(‘ShopID‘).Value:=Edit3.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘InDate‘).Value:=Edit5.Text;execSQL;end;Edit12.ReadOnly:=False;S:=StrToInt(Edit12.Text)+StrToInt(Edit4.Text);file://計算入庫后庫存圖書數量
Edit12.Text:=IntToStr(s);file://將修改后的庫存圖書數量顯示 Edit12.ReadOnly:=true;with datamoduleform.BookQuery do file://修改庫存記錄中圖書數量
begin close;SQL.Clear;SQL.Add(‘update BookRecord set Number1=:Number where BookID=:BookID‘);
Parameters.ParamByName(‘Number‘).Value:=s;
Parameters.ParamByName(‘BookID‘).Value:=Edit13.Text;execSQL;file://提交SQL語句
MessageDlg(‘記錄已成功添加!‘,mtInformation,[mbOK],0);Edit13.SetFocus;end;end;end;end;********************************************************************** procedure Tinoutform.SpeedButton2Click(Sender: TObject);begin file://入庫管理確定按鈕事件
if(Edit2.Text=‘‘)or(Edit3.Text=‘‘)or(Edit4.Text=‘‘)or(Edit5.Text=‘‘)
or(Edit6.Text=‘‘)or(Edit7.Text=‘‘)or(Edit8.Text=‘‘)or(Edit9.Text=‘‘)
or(Edit10.Text=‘‘)or(Edit11.Text=‘‘)or(Edit25.Text=‘‘)then begin file://判斷輸入信息的完整性
MessageDlg(‘請輸入所需的全部入庫信息!‘,mtInformation,[mbok],0);Edit2.SetFocus;end else begin with datamoduleform.InQuery do file://入庫信息添加 begin close;SQL.Clear;SQL.Add(‘insert into InRecord values(:InID,:BookID,:EmpID,:ShopID, :Number,:InDate)‘);file://向入庫信息表中插入記錄
Parameters.ParamByName(‘InID‘).Value:=Edit26.Text;
Parameters.ParamByName(‘BookID‘).Value:=Edit1.Text;
Parameters.ParamByName(‘EmpID‘).Value:=Edit2.Text;
Parameters.ParamByName(‘ShopID‘).Value:=Edit3.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘InDate‘).Value:=Edit5.Text;execSQL;end;with datamoduleform.BookQuery do begin close;SQL.Clear;file://在完成入庫信息的添加后,修改庫存記錄 SQL.Add(‘insert into BookRecord values(:BookID,:BookName,:Author, :Publisher,:PubDate,:Price,:BookType,:Number,:Addration)‘);
Parameters.ParamByName(‘BookID‘).Value:=Edit1.Text;
Parameters.ParamByName(‘BookName‘).Value:=Edit6.Text;
Parameters.ParamByName(‘Author‘).Value:=Edit7.Text;
Parameters.ParamByName(‘Publisher‘).Value:=Edit8.Text;
Parameters.ParamByName(‘PubDate‘).Value:=Edit9.Text;
Parameters.ParamByName(‘Price‘).Value:=Edit10.Text;
Parameters.ParamByName(‘BookType‘).Value:=Edit11.Text;
Parameters.ParamByName(‘Number‘).Value:=Edit4.Text;
Parameters.ParamByName(‘Addration‘).Value:=Edit25.Text;execSQL;end;MessageDlg(‘記錄添加成功!‘,mtInformation,[mbok],0);end;end;********************************************************************** procedure Tinoutform.SpeedButton11Click(Sender: TObject);begin file://新書入庫按鈕事件
Edit13.Text:=‘‘;Edit13.Color:=clMenu;
with datamoduleform.InQuery do file://自動入庫編號的獲取 begin close;SQL.Clear;SQL.Add(‘select * from InRecord where InID>=All(select InID from InRecord)‘);open;Edit26.Text:=FieldValues[‘InID‘]+1;
Edit26.ReadOnly:=true;Edit26.Color:=clMenu;end;with datamoduleform.BookQuery do file://自動圖書編號的獲取 begin close;SQL.Clear;SQL.Add(‘select * from BookRecord where BookID>=All(select BookID from BookRecord)‘);file://找到庫存圖書編號中最大的一個 open;Edit1.ReadOnly:=false;Edit1.Text:=FieldValues[‘BookID‘]+1;file://顯示自動生成的圖書編號
Edit1.ReadOnly:=true;Edit1.Color:=clMenu;end;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit4.Text:=‘‘;Edit5.Text:=‘‘;Edit6.ReadOnly:=false;Edit6.Text:=‘‘;Edit6.Color:=clWindow;
Edit7.ReadOnly:=false;Edit7.Text:=‘‘;Edit7.Color:=clWindow;
Edit8.ReadOnly:=false;Edit8.Text:=‘‘;Edit8.Color:=clWindow;
Edit9.ReadOnly:=false;Edit9.Text:=‘‘;Edit9.Color:=clWindow;Edit10.ReadOnly:=false;Edit10.Text:=‘‘;Edit10.Color:=clWindow;
Edit11.ReadOnly:=false;Edit11.Text:=‘‘;Edit11.Color:=clWindow;
Edit12.ReadOnly:=false;Edit12.Text:=‘‘;Edit12.Color:=clMenu;
Edit25.ReadOnly:=false;Edit25.Text:=‘‘;Edit25.Color:=clWindow;end;procedure Tinoutform.SpeedButton22Click(Sender: TObject);var s:integer;begin file://出庫管理確定按鈕事件
if(Edit24.Text=‘‘)or(Edit27.Text=‘‘)or(Edit28.Text=‘‘)then begin MessageDlg(‘請輸入完整的出庫信息!‘,mtInformation,[mbok],0);Edit24.SetFocus;end else begin if Edit27.Text>Edit21.Text file://檢查出庫數量是否小于庫存數量 then begin MessageDlg(‘庫存中的圖書數量不夠!‘,mtInformation,[mbok],0);Edit27.Text:=‘‘;Edit27.SetFocus;end else begin with datamoduleform.OutQuery do begin close;SQL.Clear;SQL.Add(‘insert into OutRecord values(:OutID,:BookID,:EmpID, :Number,:OutTime)‘);file://添加出庫記錄
Parameters.ParamByName(‘OutID‘).Value:=Edit23.Text;Parameters.ParamByName(‘BookID‘).Value:=Edit14.Text;Parameters.ParamByName(‘EmpID‘).Value:=Edit24.Text;Parameters.ParamByName(‘Number‘).Value:=Edit27.Text;Parameters.ParamByName(‘OutTime‘).Value:=Edit28.Text;execSQL;end;Edit21.ReadOnly:=False;s:=StrToInt(Edit21.Text)-StrToInt(Edit27.Text);file://計算出庫后庫存圖書數量
Edit21.Text:=IntToStr(s);file://顯示出庫后庫存圖書數量 Edit21.ReadOnly:=True;with datamoduleform.BookQuery do begin file://修改庫存圖書數量 close;SQL.Clear;SQL.Add(‘update BookRecord set Number1=:Number where BookID=:BookID‘);Parameters.ParamByName(‘Number‘).Value:=s;
Parameters.ParamByName(‘BookID‘).Value:=Edit14.Text;execSQL;end;MessageDlg(‘出庫記錄添加成功!‘,mtInformation,[mbok],0);Edit14.Text:=‘‘;Edit14.SetFocus;end;end;end;§5.5 查詢功能的實現
查詢功能包括員工信息查詢,供應商信息查詢,入庫信息查詢和出庫信息查詢。由于每一個功能的實現都差不太多,而且其窗體也差不太多,所以在這里只給出員工信息查詢窗體及其源代碼。
圖5.6 員工信息查詢窗體
procedure Tfindempform.SpeedButton1Click(Sender: TObject);Var s1,s2,s3 :String;begin file://員工記錄查詢窗體查找按鈕事件 with datamoduleform.EmpQuery do begin close;SQL.Clear;SQL.Add(‘select * from Employee‘);
SQL.Add(‘where EmployeeID Like :EmpID and EmployeeName Like :Name and Grade Like :Grade‘);file://實現模糊查詢功能 if Edit1.Text<>‘‘ then s1:=‘%‘+Edit1.Text+‘%‘ else s1:=‘%‘;Parameters.ParamByName(‘EmpID‘).Value:=s1;
if Edit2.Text<>‘‘ then s2:=‘%‘+Edit2.Text+‘%‘ else s2:=‘%‘;Parameters.ParamByName(‘Name‘).Value:=s2;if Edit3.Text<>‘‘ then s3:=‘%‘+Edit3.Text+‘%‘ else s3:=‘%‘;Parameters.ParamByName(‘Grade‘).Value:=s3;open;if FieldValues[‘EmployeeID‘]<>NULL
then findempform.Close file://在找到記錄的情況下關閉查找窗口 else begin MessageDlg(‘沒有找到你所需要的記錄!‘,mtInformation,[mbOK],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit1.SetFocus;close;SQL.Clear;SQL.Add(‘select * from Employee‘);file://刷新員工信息窗口 open;end;end;end;§5.6 系統登陸窗體模塊的實現
由于系統登陸窗體中有一幅彩圖,在這里不便給出,而只給出了系統的實現。var keyname: string;file://定義了一個全局變量,在key2中有調用 procedure Tkeyform.SpeedButton1Click(Sender: TObject);var s:string;file://登陸窗口登陸按鈕事件 begin if(Edit1.Text=‘‘)then begin MessageDlg(‘清輸入登陸姓名和密碼!‘,mtInformation,[mbok],0);Edit1.SetFocus;end else begin datamoduleform.KeyTable.Active:=true;if not datamoduleform.KeyTable.Locate(‘KeyName‘,Edit1.Text,[])file://判斷登陸名是否存在 then begin MessageDlg(‘登陸名錯誤,請重新輸入!‘,mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit1.SetFocus;end else begin with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(‘select * from Key where KeyName=:KeyName‘);Parameters.ParamByName(‘KeyName‘).Value:=Edit1.Text;open;s:=FieldValues[‘KeyNo‘];end;if s<>Edit2.Text file://判斷登陸密碼是否正確 then begin MessageDlg(‘登陸密碼錯誤,請重新輸入!‘,mtInformation,[mbok],0);Edit2.Text:=‘‘;Edit2.SetFocus;end else begin keyname:=Edit1.Text;keyform.Hide;mainform.Show;mainform.WindowState:=wsMaximized;end;end;end;end;§5.7 用戶管理功能的實現 5.7.1 用戶管理主窗體
圖5.7 用戶管理主窗體 5.7.2 密碼修改窗體模塊的實現
圖5.8 密碼修改窗體
procedure Tkey2form.SpeedButton1Click(Sender: TObject);begin file://密碼修改窗口修改按鈕事件
if(Edit1.Text=‘‘)or(Edit2.Text=‘‘)or(Edit3.Text=‘‘)then begin MessageDlg(‘請輸入完整的信息。‘,mtInformation,[mbok],0);Edit1.SetFocus;end else begin if Not datamoduleform.KeyTable.Locate(‘KeyNo‘,Edit1.Text,[])then begin MessageDlg(‘原密碼輸入錯誤,不能修改新密碼!‘,mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit1.SetFocus;end else begin if Edit2.Text<>Edit3.Text then begin MessageDlg(‘兩次密碼輸入不同,請重新輸入新密碼!‘,mtInformation,[mbok],0);
Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit2.SetFocus;end else begin file://在數據庫中修改密碼 with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(‘update key set KeyNo=:KeyNo where KeyName=:KeyName‘);Parameters.ParamByName(‘KeyName‘).Value:=keyname;Parameters.ParamByName(‘KeyNo‘).Value:=Edit2.Text;execSQL;MessageDlg(‘密碼修改成功!‘,mtInformation,[mbok],0);key2form.Close;end;end;end;end;end;5.7.3 用戶注冊窗體模塊的實現 圖5.9 用戶注冊窗體
procedure Tkey3form.SpeedButton1Click(Sender: TObject);begin file://用戶注刪窗口注刪按鈕事件
if(Edit1.Text=‘‘)or(Edit2.Text=‘‘)or(Edit3.Text=‘‘)then begin MessageDlg(‘請輸入完整的信息!‘,mtInformation,[mbok],0);Edit1.SetFocus;end else begin if datamoduleform.KeyTable.Locate(‘KeyName‘,Edit1.Text,[])file://判斷用戶名是否存在,系統不允許用戶名重復 then begin MessageDlg(‘用戶名已存在,請輸入新的用戶名和密碼!‘, mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit1.SetFocus;end else begin if Edit2.Text<>Edit3.Text then begin MessageDlg(‘您輸入的兩個密碼不相同,請重新輸入!‘,mtInformation,[mbok],0);
Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit2.SetFocus;end else begin with datamoduleform.KeyQuery do file://在數據庫中添加該用戶 begin close;SQL.Clear;SQL.Add(‘insert into Key values(:KeyName,:KeyNo)‘);Parameters.ParamByName(‘KeyName‘).Value:=Edit1.Text;Parameters.ParamByName(‘KeyNo‘).Value:=Edit2.Text;execSQL;end;MessageDlg(‘新用戶添加成功,您可以繼續添加用戶,或按“取消”退出。‘,mtInformation,[mbok],0);
Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit3.Text:=‘‘;Edit1.SetFocus;end;end;end;end;5.7.4 用戶注銷窗體模塊的實現
圖5.10 用戶注銷窗體
procedure Tkey4form.SpeedButton1Click(Sender: TObject);var s:string;begin file://用戶注銷窗口注銷按鈕事件 if(Edit1.Text=‘‘)or(Edit2.Text=‘‘)
then MessageDlg(‘請輸入完整的信息!‘,mtInformation,[mbok],0)else begin if Not datamoduleform.KeyTable.Locate(‘KeyName‘,Edit1.Text,[])file://判斷用戶名是否存在,用戶名必須存在,才可以刪除 then begin MessageDlg(‘您所輸入的用戶名不存在,請重新輸入或按“取消”退出。‘, mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit1.SetFocus;end else begin with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(‘select * from Key where KeyName=:KeyName‘);Parameters.ParamByName(‘KeyName‘).Value:=Edit1.Text;open;s:=FieldValues[‘KeyNo‘];end;if s<>Edit2.Text file://判斷該用戶名下的密碼是否正確 then begin MessageDlg(‘您所輸入的密碼不正確,請重新輸入或按“取消”退出。‘, mtInformation,[mbok],0);Edit2.Text:=‘‘;Edit2.SetFocus;end else begin file://從數據庫中刪除該用戶 with datamoduleform.KeyQuery do begin close;SQL.Clear;SQL.Add(‘delete from Key where KeyName=:KeyName‘);Parameters.ParamByName(‘KeyName‘).Value:=Edit1.Text;execSQL;end;MessageDlg(‘用戶已成功刪除,您可以繼續刪除用戶,或按“取消”退出。‘, mtInformation,[mbok],0);Edit1.Text:=‘‘;Edit2.Text:=‘‘;Edit1.SetFocus;end;end;end;end;
結束語
本 系統是一個面向小型圖書企業,具有一定實用性的數據庫信息管理系統。它主要完成對圖書倉庫的一系列管理,包括入庫、出庫、庫存以及員工和供應商信息管理。本系統采用當前流行的面向對象的開發工具—Delphi來完成整個系統的設計,在數據庫的設計上利用了Access的便利性和實用性。
本系統具有 相當的實用功能。在查詢方面,系統實現了多條件任意字段的模糊查詢,同時在分類查詢上實現了動態生成,系統可以自動識別用戶不同的輸入。在圖書入庫、出庫 和庫存三者之間建立了良好的鏈接關系,某一部分地修改均會自動引發系統對與其相關的部分進行連鎖修改。在用戶管理方面,系統較好地實現了用戶注冊,用戶注 銷和密碼修改等各項功能。系統在設計過程中不可避免地遇到了各種各樣的問題,由于整個系統完全都是由個人設計的,有關Delphi許多細節問題都要靠自己去摸索,加之本人水平有限,并沒有完全地理解Delphi的強大功能,而且還存在著許多不足之處。如: ※ 受開發條件和開發時間的限制,本系統只利用了本地數據庫Access,它同應用程序處于同一系統中,能存儲的數據量也有一定限制,并沒有發揮出Delphi其數據庫方面的優勢;
※ 報表打印功能尚不夠全面完善,不能實現動態報表; ※ 在一些數據輸入時沒有及時的進行數據格式校驗,不能保證數據輸入的絕對正確性。
※ 由于時間關系,系統功能實現不夠完善,使用不是很方便,比如,沒有實現多條記錄的連鎖刪除和添加以及數據的導入功能。
這些都是需要完善的地方,該系統離實際使用也還有相當的距離,需要我進行不斷地補充和完善。
通過本次畢業設計我學到了不少新的東西,也發現了大量的問題,有些在設計過程中已經解決,有些還有待今后慢慢學習。只要學習就會有更多的問題,有更多的難點,但也會有更多的收獲。
考 文 獻
[1] 鄭榮貴、黃平、谷會東,Delphi 6.0數據庫開發與應用,中科多媒體電子出版社,2002 [2] 伍俊良,Delphi 6控件應用實例教程,北京希望電子出版社,2002 [3] 盧國俊,Delphi 6數據庫開發,電子工業出版社,2002 [4] 邊萌,Delphi 編程起步,機械工業出版社,2002 [5] 伍俊良,Delphi 6課程設計案例精編,中國水利水電出版社,2002 [6] 丁寶康,數據庫原理,經濟科學出版社,2000 [7] 陸麗娜,軟件工程,經濟科學出版社,2000