3、多用戶及其權限管理的設計 開發數據庫管理類的軟件,不可能不考慮多用戶和用戶權限設置的問題。儘管目前市面上的大、中型的後臺數據庫系統軟件都提供了多用戶,以及細至某個數據庫內某張表的權限設置的功能,我我的建議:一套成熟的數據庫管理軟件,仍是應該自行設計用戶管理這塊功能,緣由有二: 1.那些大、中型後臺數據庫系統軟件所提供的多用戶及其權限設置都是針對數據庫的共有屬性,並不必定能徹底知足某些特例的需求; 2.不要過多的依賴後臺數據庫系統軟件的某些特殊功能,多種大、中型後臺數據庫系統軟件之間並不徹底兼容。不然一旦往後須要轉換數據庫平臺或後臺數據庫系統軟件版本升級,以前的架構設計極可能沒法重用。 下面看看如何自行設計一套比較靈活的多用戶管理模塊,即該數據庫管理軟件的系統管理員能夠自行添加新用戶,修改已有用戶的權限,刪除已有用戶。 首先,分析用戶需求,列出該數據庫管理軟件全部須要實現的功能;而後,根據必定的聯繫對這些功能進行分類,即把某類用戶需使用的功能歸爲一類;最後開始建 表: 功能表(Function_table) 名稱 類型 約束條件 說明 f_id int 無重複 功能標識,主鍵 f_name char(20) 不容許爲空 功能名稱,不容許重複 f_desc char(50) 容許爲空 功能描述 用戶組表(User_group) 名稱 類型 約束條件 說明 group_id int 無重複 用戶組標識,主鍵 group_name char(20) 不容許爲空 用戶組名稱 group_power char(100) 不容許爲空 用戶組權限表,內容爲功能表f_id的集合 用戶表(User_table) 名稱 類型 約束條件 說明 user_id int 無重複 用戶標識,主鍵 user_name char(20) 無重複 用戶名 user_pwd char(20) 不容許爲空 用戶密碼 user_type int 不容許爲空 所屬用戶組標識,和User_group.group_id關聯 採用這種用戶組的架構設計,當須要添加新用戶時,只需指定新用戶所屬的用戶組;當之後系統須要添加新功能或對舊有功能權限進行修改時,只用操做 功能表和用戶組表的記錄,原有用戶的功能便可相應隨之變化。固然,這種架構設計把數據庫管理軟件的功能斷定移到了前臺,使得前臺開發相對複雜一些。可是, 當用戶數較大(10人以上),或往後軟件升級的機率較大時,這個代價是值得的。 4、簡潔的批量m:n設計 碰到m:n的關係,通常都是創建3個表,m一個,n一個,m:n一個。可是,m:n有時會遇到批量處理的狀況,例如到圖書館借書,通常都是容許 用戶同時借閱n本書,若是要求按批查詢借閱記錄,即列出某個用戶某次借閱的全部書籍,該如何設計呢?讓咱們建好必須的3個表先: 書籍表(Book_table) 名稱 類型 約束條件 說明 book_id int 無重複 書籍標識,主鍵 book_no char(20) 無重複 書籍編號 book_name char(100) 不容許爲空 書籍名稱 …… 借閱用戶表(Renter_table) 名稱 類型 約束條件 說明 renter_id int 無重複 用戶標識,主鍵 renter_name char(20) 不容許爲空 用戶姓名 …… 借閱記錄表(Rent_log) 名稱 類型 約束條件 說明 rent_id int 無重複 借閱記錄標識,主鍵 r_id int 不容許爲空 用戶標識,和Renter_table.renter_id關聯 b_id int 不容許爲空 書籍標識,和Book_table.book_id關聯 rent_date datetime 不容許爲空 借閱時間 …… 爲了實現按批查詢借閱記錄,咱們能夠再建一個表來保存批量借閱的信息,例如: 批量借閱表(Batch_rent) 名稱 類型 約束條件 說明 batch_id int 無重複 批量借閱標識,主鍵 batch_no int 不容許爲空 批量借閱編號,同一批借閱的batch_no相同 rent_id int 不容許爲空 借閱記錄標識,和Rent_log.rent_id關聯 batch_date datetime 不容許爲空 批量借閱時間 這樣的設計好嗎?咱們來看看爲了列出某個用戶某次借閱的全部書籍,須要如何查詢?首先檢索批量借閱表(Batch_rent),把符合條件的的 全部記錄的rent_id字段的數據保存起來,再用這些數據做爲查詢條件帶入到借閱記錄表(Rent_log)中去查詢。那麼,有沒有什麼辦法改進呢?下 面給出一種簡潔的批量設計方案,不需添加新表,只需修改一下借閱記錄表(Rent_log)便可。修改後的記錄表(Rent_log)以下: 借閱記錄表(Rent_log) 名稱 類型 約束條件 說明 rent_id int 無重複 借閱記錄標識,主鍵 r_id int 不容許爲空 用戶標識,和Renter_table.renter_id關聯 b_id int 不容許爲空 書籍標識,和Book_table.book_id關聯 batch_no int 不容許爲空 批量借閱編號,同一批借閱的batch_no相同 rent_date datetime 不容許爲空 借閱時間 …… 其中,同一次借閱的batch_no和該批第一條入庫的rent_id相同。舉例:假設當前最大rent_id是64,接着某用戶一次借閱了3 本書,則批量插入的3條借閱記錄的batch_no都是65。以後另一個用戶租了一套碟,再插入出租記錄的rent_id是68。採用這種設計,查詢批 量借閱的信息時,只需使用一條標準T_SQL的嵌套查詢便可。固然,這種設計不符合3NF,可是和上面標準的3NF設計比起來,哪種更好呢?答案就不用我說了吧。 5、冗餘數據的取捨 上篇的「樹型關係的數據表」中保留了一個冗餘字段,這裏的例子更進一步——添加了一個冗餘表。先看看例子:我原先所在的公司爲了解決員工的工做 餐,和附近的一家小餐館聯繫,天天吃飯記帳,費用按人數平攤,月底由公司現金結算,每一個人每月的工做餐費從工資中扣除。固然,天天吃飯的人員和人數都不 是固定的,並且,因爲每頓工做餐的所點的菜色不一樣,每頓的花費也不相同。例如,星期一中餐5人花費40元,晚餐2人花費20,星期二中餐6人花費36元, 晚餐3人花費18元。爲了方便計算每一個人每月的工做餐費,我寫了一個簡陋的就餐記帳管理程序,數據庫裏有3個表: 員工表(Clerk_table) 名稱 類型 約束條件 說明 clerk_id int 無重複 員工標識,主鍵 clerk_name char(10) 不容許爲空 員工姓名 每餐總表(Eatdata1) 名稱 類型 約束條件 說明 totle_id int 無重複 每餐總表標識,主鍵 persons char(100) 不容許爲空 就餐員工的員工標識集合 eat_date datetime 不容許爲空 就餐日期 eat_type char(1) 不容許爲空 就餐類型,用來區分中、晚餐 totle_price money 不容許爲空 每餐總花費 persons_num int 不容許爲空 就餐人數 就餐計費細表(Eatdata2) 名稱 類型 約束條件 說明 id int 無重複 就餐計費細表標識,主鍵 t_id int 不容許爲空 每餐總表標識,和Eatdata1.totle_id關聯 c_id int 不容許爲空 員工標識標識,和Clerk_table.clerk_id關聯 price money 不容許爲空 每人每餐花費 其中,就餐計費細表(Eatdata2)的記錄就是把每餐總表(Eatdata1)的一條記錄按就餐員工平攤拆開,是個徹徹底底的冗餘表。當 然,也能夠把每餐總表(Eatdata1)的部分字段合併到就餐計費細表(Eatdata2)中,這樣每餐總表(Eatdata1)就成了冗餘表,不過這 樣所設計出來的就餐計費細表重複數據更多,相比來講仍是上面的方案好些。可是,就是就餐計費細表(Eatdata2)這個冗餘表,在作每個月每人餐費統計的 時候,大大簡化了編程的複雜度,只用相似這麼一條查詢語句便可統計出每人每個月的寄餐次數和餐費總賬: SELECT clerk_name AS personname,COUNT(c_id) as eattimes,SUM(price) AS ptprice FROM Eatdata2 JOIN Clerk_tabsle ON (c_id=clerk_id) JOIN eatdata1 ON (totleid=tid) WHERE eat_date>=CONVERT(datetime,'"&the_date&"') AND eat_date 想象一下,若是不用這個冗餘表,每次統計每人每個月的餐費總賬時會多麻煩,程序效率也夠嗆。那麼,到底何時能夠增長必定的冗餘數據呢?我認爲有2個原則: 一、用戶的總體需求。當用戶更多的關注於,對數據庫的規範記錄按必定的算法進行處理後,再列出的數據。若是該算法能夠直接利用後臺數據庫系統的 內嵌函數來完成,此時能夠適當的增長冗餘字段,甚至冗餘表來保存這些通過算法處理後的數據。要知道,對於大批量數據的查詢,修改或刪除,後臺數據庫系統的 效率遠遠高於咱們本身編寫的代碼。 二、簡化開發的複雜度。現代軟件開發,實現一樣的功能,方法有不少。儘管沒必要要求程序員精 通絕大部分的開發工具和平臺,可是仍是須要了解哪一種方法搭配哪一種開發工具的程序更簡潔,效率更高一些。冗餘數據的本質就是用空間換時間,尤爲是目前硬件的 發展遠遠高於軟件,因此適當的冗餘是能夠接受的。不過我仍是在最後再強調一下:不要過多的依賴平臺和開發工具的特性來簡化開發,這個度要是沒把握好的話, 後期維護升級會栽大跟頭的。程序員