范式下的Oracle數據庫設計
數據關系的復雜性導致了表中數據冗余的存在,數據冗余增加了維護數據庫的負擔,也占用了大量的磁盤空間,直接造成性能下降。為了消除這些負面影響,就應該對數據庫表格進行規范化,使其遵守一定的規則的,尤其是數據庫設計范式。
關系必須是規范化的,簡單說來,就是在結構表設計時,消除冗余性和不協調的從屬關系。即每一個分量必須是不可分的數據項,但是這只是最基本的規范化。規范化理論就是研究如何將一個不好的關系模式轉化為好的關系模式的理論,規范化理論是圍繞范式而建立的。規范化理論認為,一個關系數據庫中所有的關系,都應滿足一定的規范(約束條件)。規范化理論把關系應滿足的規范要求分為幾級,滿足最低要求的一級叫做第一范式(1NF),在第一范式的基礎上提出了第二范式(2NF),在第二范式的基礎上又提出了第三范式(3NF),以後又提出了BCNF范式,4NF,5NF,以及“域/關鍵字”范式。范式的等級越高,應滿足的約束集條件也越嚴格。規范的每一級別都依賴於它的前一級別,例如若一個關系模式滿足2NF,則一定滿足1NF。
在Oracle上設計數據庫時更要符合范式的要求,如果把一個不符合規范的數據庫放在Oracle中,是不會突出Oracle的性能的,甚至是非常糟糕。
例如:學生的成績表,我們一般都要求打印一目了然。
這也是符合1NF的,但如果是在數據庫中定義的表結構也這樣,則是不完善的,是有潛在沖突的。如要增加考試科目,就得更改表結構,特別是大學,專業多、科目多,而有些科目是選學的,這將會使表結構變得相當復雜,有多少科目就得有多少個科目的字段,有部分字段值必然為空;這個表是指某次測驗的還是期中或期末考試的成績呢?分辨不出,於是每一次成績都要造一張類似的表,必然表格較多。不僅浪費大量的磁盤空間,還會給程序的編寫帶來極大的困難。
在數據范式理論的指導下,對數據庫表格進行規范化,使其結構更合理,消除存儲異常,使數據冗余盡量最小,便於插入、刪除和更新,進一步保持了數據的完整性。經過探索,我在成績管理系統的設計上采用了如下的表結構,這個表結構能以不變應用多變,不管是科目的增加,還是教師的變動,都能適應,符合數據的規范要求。
由此看出,經數據規范化的數據雖然使數據冗余小,便於插入、刪除和更新,但如果直接輸出是不符合人們觀看習慣的,必需要把其輸出為上面表1的格式才行,這就是列向表生成橫向表的問題,即交叉表的生成。
動態交叉表的生成
為了簡述起見,在學生基本信息表中,只建兩個字段,學號、姓名,其他的諸如性別、科代碼等則略。其中班、教師代碼庫、考試次數標志(即第幾次測驗,還是期中、期末考試)等也略,只保留下面數據結構足以能說明交叉表生成的過程。
各表結構簡化如下:
學生基本信息表:JBXX
xh char(13) //學號
xm char(8) //姓名,針對不同情況,可用變長字符。
科目代碼表:KMDM
no number(3) //科目代號,現可用900多科目可用,若不夠,可定義四位。
mc varchar(20) //科目中文名稱。
成績表: CJ
xh char(13) //學號,關聯JBXX的XH。
xq number(2) //學期,指該學生所在校的學期。
km number(3) //科目代號。
cj number(3) //該科成績。
至此,數據表結構已全部建好,此時的任務是把下面表3的數據進行生成交叉表,表4。
交叉表的生成,在Oracle中可以用SQL語句實現。
select jbxx.xh,jbxx.xm , (select cj.cj from cj where cj.xh=jbxx.xh and cj.xq=1 and cj.km=1) as km1 , (select cj.cj from cj where cj.xh=jbxx.xh and cj.xq=1 and cj.km=2) as km2 , (select cj.cj from cj where cj.xh=jbxx.xh and cj.xq=1 and cj.km==3) as km3 from jbxx where <班級或專業條件> order by jbxx.xh
Java語言有“編寫一次,隨處運行”的跨平台能力,具有強大的網絡能力。Oracle是一種關系型的大型數據庫,可在多種硬件平台上運行,支持多種操作系統,支持大數據庫、多用戶的高性能的事務處理,以其強大的功能和穩定性而著稱。因此建議用Java結合Oracle編寫程序。下面給出在Java語言中的具體實現過程。
注:為了簡述方便,下面的程序已簡略,在實踐應用中,還要考慮很多問題,並且一般把它做成bean來用。
程序如下:
import Java.sql.*;//導入類庫
public class sjk{
public static void main(String[] args) throws Exception {
Connection conn;
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
String sourceURL="jdbc:Oracle:thin:@server:1521:orcl";
String user="scott";
String passWord="tiger";
conn=DriverManager.getConnection(sourceURL,user,passWord);
Statement stmt = conn.createStatement();
Statement stmt1 = conn.createStatement();
String sql_km="select no,mc from km";
// String bb_tj="0441010101";以後實際使用要加上班或級或專業條件.
ResultSet rs_km = stmt.executeQuery(sql_km);
String title=" 學號 姓名 ";
String sql1="( select cj.cj from cj where cj.xh=jbxx.xh and cj.xq=1 and cj.km=";
String sql=" select jbxx.xh,jbxx.xm ,";
while (rs_km.next())
{
String sql_sum=" select sum(cj) as s1 from cj where "+
" cj.xq=1 and cj.km="; //在實際使用中要加上班級條件
sql_sum=sql_sum+rs_km.get