四、需求分析→數(shù)據(jù)庫設(shè)計(jì)
??
?? 從這開始,就真正進(jìn)入項(xiàng)目實(shí)戰(zhàn)啦。先說點(diǎn)體會(huì),我剛開始接觸編程的時(shí)候,都是編寫一些小東西,往往都是半天或者一天什么的就編完了,那時(shí)候根本沒想過做程序之前還要有需求分析。經(jīng)過快兩年的學(xué)習(xí),接觸的都是比較大的系統(tǒng),才明白沒有需求分析的程序都太業(yè)余了,沒有任何技術(shù)含量。對(duì)于一個(gè)系統(tǒng)來說,如果需求分析不到位,那么將有災(zāi)難性的后果,從這節(jié)的小標(biāo)題就能看出,需求是數(shù)據(jù)庫設(shè)計(jì)的基石,需求定了,數(shù)據(jù)庫基本上就定了,數(shù)據(jù)庫定了,程序的基本功能也就定了。我們以一個(gè)簡(jiǎn)單的學(xué)生管理系統(tǒng)為例子,來分析一下需求。分析需求地球人一般都是用UML圖,啥是UML圖呢,就是一種把程序用圖形表示的標(biāo)準(zhǔn),它可以表示需求、程序流程、程序模塊、程序功能等等,可以說,UML圖畫完了,程序基本上就出來了,目前比較好的畫UML的工具是Rational rose,不多說啦,剩下的就交給google了。本系統(tǒng)的需求非常簡(jiǎn)單,就是老師可以添加、刪除、修改學(xué)生記錄,學(xué)生的記錄包括:學(xué)號(hào)、年級(jí)、班級(jí)、姓名、性別、年齡、備注(這些就是字段)。根據(jù)這些敘述,我們可以畫出UML用例圖(用例圖就是用來分析需求的):
?
?
?? 根據(jù)需求分析我們就可以設(shè)計(jì)數(shù)據(jù)庫了,非常“簡(jiǎn)單”嘛,需要一個(gè)表就行了,把它命名為student表,里邊添加剛剛提的那些字段就可以了。注意,數(shù)據(jù)庫中的一切,包括:數(shù)據(jù)庫名、表名、字段名、存儲(chǔ)過程等等,都要用英文,不可以出現(xiàn)中文,因?yàn)樵凼菍I(yè)菜鳥,不走業(yè)余路。接著往下看,教你如何創(chuàng)建數(shù)據(jù)庫。??
?? 作為專業(yè)教程,俺不會(huì)教你用鼠標(biāo)建立數(shù)據(jù)庫,咱們要用T-SQL語句建立數(shù)據(jù)庫,也就是寫數(shù)據(jù)庫腳本。這樣建立數(shù)據(jù)庫,相當(dāng)于留了個(gè)備份,無論到哪,只要有SQL環(huán)境,直接執(zhí)行一下腳本數(shù)據(jù)就建好了,非常方便快捷,就算是第一次寫腳本,也比用鼠標(biāo)建立數(shù)據(jù)庫快。在大型系統(tǒng)開發(fā)時(shí),腳本還可以作為數(shù)據(jù)庫維護(hù)的依據(jù),非常有用。那么怎樣寫呢,打開SQL server 2005 Management Studio,輸入帳號(hào)密碼登錄平臺(tái),然后點(diǎn)一下左上角的"新建查詢"就可以打開查詢分析器了,我們可以在這輸入任何SQL語句。
?? 第一步先創(chuàng)建數(shù)據(jù)庫,我先把創(chuàng)建數(shù)據(jù)庫的標(biāo)準(zhǔn)格式給大家:
create database studentManager On primary ( name=student_data, filename='E:\SQL Server2008 SQLFULL_CHS\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\student_data.mdf', size=3, maxsize=unlimited, filegrowth=1 ) Log on (name=student_log, filename='E:\SQL Server2008 SQLFULL_CHS\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\student_log.ldf', size=1, maxsize=20,
?
?? 相信看著這個(gè)很多人都蒙了,簡(jiǎn)單說一下,其實(shí)這么多代碼,也就第一句最重要,意思是創(chuàng)建一個(gè)名字叫studentManager的數(shù)據(jù)庫。On primary下邊的是對(duì)數(shù)據(jù)庫的一些初始設(shè)置,比如:路徑、初始大小、增量等等。Log on下邊的是對(duì)數(shù)據(jù)庫日志的設(shè)置,也是那么幾項(xiàng)。很明確的告訴大家,除非是特殊需求,否則我們沒必要管那么多,默認(rèn)的就夠咱們用了,創(chuàng)建數(shù)據(jù)庫就一句話:create database studentManager,輸入完后點(diǎn)一下工具欄上的“執(zhí)行”,就搞定啦。數(shù)據(jù)庫建完了,就該在數(shù)據(jù)庫里建表了,還是先給出代碼:
?
--指定數(shù)據(jù)庫 use t_studentManager; --創(chuàng)建t_student表 create table t_student ( number varchar(20) PRIMARY KEY, --PRIMARY KEY 是主鍵約束 grade varchar(10) NOT NULL, --NOT NULL是非空約束 class varchar(10) NOT NULL, [name] varchar(20) NOT NULL, --name屬于sql保留字,所以用方括號(hào)括起來 sex varchar(1) NOT NULL CHECK(sex in ('男','女')), --CHECK約束,意思是性別字段只能是男或女。 age int NOT NULL, remark varchar(100), addTime datetime DEFAULT(getdate())--默認(rèn)值約束,getdate()獲取服務(wù)器時(shí)間 );
?? 給大家解釋一下,剛剛我們創(chuàng)建完數(shù)據(jù)庫,在這要引用一下,也就是use,這樣才可以在指定數(shù)據(jù)庫中建表。
??create table當(dāng)然就是建表的意思了,在表名前最好加一個(gè)"t_",表示是表(table),這樣容易區(qū)分,而且專業(yè)。括號(hào)里的就是這個(gè)表中的字段,格式是:字段名類型 約束,注意每個(gè)字段寫完后邊都要加逗號(hào)(最后一個(gè)就不用加啦),表示分隔。舉這個(gè)例子,約束用的還是比較全的,重點(diǎn)說說約束。約束可是數(shù)據(jù)庫中相當(dāng)重要的東西,它保證了數(shù)據(jù)庫的安全和穩(wěn)定,同時(shí)也保證了數(shù)據(jù)完整性。約束主要有6種,分別是:NOT NULL約束(非空約束)、PRIMARY KEY約束(主鍵約束)、FOREIGN KEY約束(外鍵約束)、UNIQUE約束(唯一約束)、CHECK約束(檢查約束)、DEFAULT約束(默認(rèn)值約束)。這些約束可以用在任何字段的后邊,一個(gè)字段也可以有多個(gè)約束,用空格分隔即可,比如上邊的sex字段,就同時(shí)使用了非空約束和檢查約束。當(dāng)然,有些約束只能用一次,比如主鍵約束。我只是提了一下這些常用約束,大家了解我的目的就達(dá)到了,以后具體用到,再去google,就怕你不知道有這些約束。在查詢分析器中執(zhí)行這段代碼,表就建立好了,提示一下:SQL查詢分析器可以選中執(zhí)行,也就是你選中那些代碼就執(zhí)行那些代碼,建表的時(shí)候注意不要再次執(zhí)行建數(shù)據(jù)庫的語句哦。
?
?? 五、優(yōu)化數(shù)據(jù)庫。
?? 數(shù)據(jù)庫設(shè)計(jì)是程序的根基,也是一門藝術(shù)。上一節(jié)我們?cè)O(shè)計(jì)的數(shù)據(jù)庫,太隨意了,什么都沒有考慮,作為專業(yè)菜鳥,這樣是不行的。
?? 優(yōu)化數(shù)據(jù)庫,先要了解數(shù)據(jù)庫設(shè)計(jì)三范式,簡(jiǎn)單說下:
?? 1.第一范式:是指數(shù)據(jù)庫表的每一列都是不可分割的基本數(shù)據(jù)項(xiàng),同一列中不能有多個(gè)值,即實(shí)體中的某個(gè)屬性不能有多個(gè)值或者不能有重復(fù)的屬性。
?? 2.第二范式:第二范式需要確保數(shù)據(jù)庫表中的每一列都和主鍵相關(guān),而不能只與主鍵的某一部分相關(guān)(主要針對(duì)聯(lián)合主鍵而言)。
?? 3.第三范式:第三范式需要確保數(shù)據(jù)表中的每一列數(shù)據(jù)都和主鍵直接相關(guān),而不能間接相關(guān)。
?? 這三個(gè)范式大致的意思就是:數(shù)據(jù)庫中表的職責(zé)要單一,依賴關(guān)系明確,盡量減少數(shù)據(jù)庫數(shù)據(jù)冗余。從網(wǎng)上查,可以查到很多個(gè)人理解,我在這也不理解了,核心思想就是我剛剛說的。我首先聲明,三范式只是一個(gè)整體的指導(dǎo)思想,并不可能完全遵從,有時(shí)候數(shù)據(jù)冗余未必是壞事,要考慮實(shí)際情況。
?? 很明顯,剛剛我們?cè)O(shè)計(jì)的數(shù)據(jù)庫不符合三范式的要求。在此表中學(xué)生應(yīng)該依賴的是學(xué)號(hào),而我們冒昧的把班級(jí)、年級(jí)也放在了這里,學(xué)生當(dāng)然也應(yīng)該依賴于班級(jí)、年級(jí)。這樣一來,表就亂了,造成的直接后果就是數(shù)據(jù)不完整,比如我們由于失誤,插入了一個(gè)年級(jí)是100的學(xué)生,而根本就沒有100這個(gè)班級(jí)。這樣還有個(gè)比較大的問題就是數(shù)據(jù)冗余,因?yàn)槲覀兠坎迦胍粋€(gè)學(xué)生,不得不記錄一次班級(jí)、年級(jí),造成大量無用數(shù)據(jù)。所以我們要改,要把一個(gè)表拆成三個(gè),分別是:年級(jí)表、班級(jí)表、學(xué)生表。這樣一來,數(shù)據(jù)庫就顯得漂亮多了。剛剛是一個(gè)表,我們還應(yīng)付得過來,現(xiàn)在三個(gè)表,記不住了怎么辦?別急,剛剛提到了UML圖,它可以用來設(shè)計(jì)數(shù)據(jù)庫。在程序設(shè)計(jì)過程中,數(shù)據(jù)庫中的每一個(gè)表,都會(huì)在程序中映射成一個(gè)類,而表中的每一個(gè)字段,都是類中的一個(gè)屬性,它們的類型是一致的,我們管他叫做實(shí)體類(可以提前google一下三層架構(gòu)哦),這時(shí)我們可以借助于UML中的類圖畫出數(shù)據(jù)庫的結(jié)構(gòu)。如下圖:
?
?
?? 通過UML類圖,清晰的描述了表之間的關(guān)系。所以,在大型項(xiàng)目開發(fā)中,必須借助工具設(shè)計(jì)數(shù)據(jù)庫,展示數(shù)據(jù)庫的結(jié)構(gòu)和關(guān)系,這樣我們才能優(yōu)化、改進(jìn)數(shù)據(jù)庫,數(shù)據(jù)庫不是一下就能設(shè)計(jì)成功的,往往要根據(jù)需求的理解而發(fā)生變動(dòng)。很多童鞋可能會(huì)問為什么用實(shí)體類,我只說一句話:用實(shí)體類便于在程序中對(duì)數(shù)據(jù)庫進(jìn)行操作,實(shí)體類是對(duì)數(shù)據(jù)的打包,便于數(shù)據(jù)傳遞。剩下的就要去google啦~不多說。這下我們的數(shù)據(jù)庫設(shè)計(jì)算是完工了,刪掉原來的數(shù)據(jù)庫,對(duì)照這UML實(shí)體類圖寫優(yōu)化后的數(shù)據(jù)庫腳本,代碼如下:
?
--創(chuàng)建數(shù)據(jù)庫 create database studentManager; --指定數(shù)據(jù)庫 use t_studentManager; --創(chuàng)建年級(jí)表 create table t_grade ( id bigint IDENTITY(1,1) PRIMARY KEY, [name] varchar(10) NOT NULL ); --創(chuàng)建班級(jí)表 create table t_class ( id bigint IDENTITY(1,1) PRIMARY KEY, gradeID bigint NOT NULL, [name] varchar(10) NOT NULL, CONSTRAINT FK_class_gradeID FOREIGN KEY(gradeID) REFERENCES t_grade(id) --外鍵約束 ); --創(chuàng)建t_student表 create table t_student ( number varchar(20) PRIMARY KEY, --PRIMARY KEY 是主鍵約束 classID bigint NOT NULL, [name] varchar(20) NOT NULL, --name屬于sql保留字,所以用方括號(hào)括起來 sex varchar(1) NOT NULL CHECK(sex in ('男','女')), --CHECK約束,意思是性別字段只能是男或女。 age int NOT NULL, remark varchar(100), addTime datetime DEFAULT(getdate()),--默認(rèn)值約束,getdate()獲取服務(wù)器時(shí)間 CONSTRAINT FK_student_classID FOREIGN KEY(classID) REFERENCES t_class(id) --外鍵約束 );
?? 在講代碼之前,必須先說什么是外鍵約束,外鍵約束就是:A表的某個(gè)字段用到了B表的主鍵字段,那么A表中的這個(gè)字段就叫外鍵,A、B兩個(gè)表間的約束關(guān)系就叫外鍵約束。A表的外鍵字段必須依賴于B表的主鍵字段,如果向A表外鍵字段中添加一個(gè)B表主鍵字段中不存在的數(shù)據(jù),那么將失敗。外鍵約束保證了數(shù)據(jù)的完整性和合理性。
?? 這段代碼,我還是要重點(diǎn)說說約束,與上一次創(chuàng)建表不同的是,不僅僅是表多了,而且最后多了外鍵約束,CONSTRAINT是創(chuàng)建一個(gè)約束,后邊接約束名;FOREIGN KEY代表該約束是外鍵約束,括號(hào)里寫字段名,代表這個(gè)字段是外鍵;REFERENCES是參考的意思,也就是參考哪個(gè)表里的哪個(gè)字段,也就是主鍵在哪,后邊接"表名(字段名)"。其實(shí)我是故意把它寫在最后的邊的,外鍵約束也是約束,完全可以放在字段定義的最后邊,也就是NOT NULL那個(gè)位置上,我這樣寫是想告訴大家還有另一種寫法,所有的約束都可以類似這樣寫,就是換個(gè)位置,我現(xiàn)在提出來避免大家以后見到發(fā)蒙。需要注意的是,創(chuàng)建表的括號(hào)里,無論是寫約束還是寫字段,都要用逗號(hào)分隔,千萬別忘了。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
