一、实验目的

通过该实验把数据库的理论知识(数据库和数据表的设计理论、视图、索引、存储过程、触发器、数据库备份、数据库安全等)应用到具体的综合实例中,达到数据库知识整合的目的。完成学生成绩管图书借阅理系统基本功能设计,提高学生的分析问题、解决问题的能力。

二、设备与环境

硬件:多媒体计算机

软件:WindowsXP以上的操作系统、Oracle 10g 数据库管理系统

三、实验内容及实验结果

1.数据库设计

设计思想

     创建一个表空间LIBTBS,用于保存图书管理系统的各种表,首先需要定义数据文件的存储地址,并且定义该数据文件的大小为500M、的分配方式为自动扩展、表空间的管理方式为本地管理。

   然后,将该表空间对应的数据文件的扩展方式定义为自动扩展,当该数据文件被写满时,每一次扩展50M,最大的数据文件大小为1000M,防止数据文件被填满而无法扩展。

 

2.数据表设计

设计思想

创建四个表,定义在"SCOTT"模式下,存储在之前建立的表空间LIBTBS中。这四个表是读者表、图书表、借阅表和历史借阅表。

读者表的作用是存放读者信息,读者号,读者姓名,性别,年级,学院,等等读者相关的信息。

图书表的作用是存放图书信息,ISBN,书名,作者,存储量,价格等图书的相关信息。

借阅表的作用是对读者表和图书表的一个链接,显示哪些人借的哪些书。借阅的日期和借阅过程产生的序列号信息。

借阅历史表的作用是记录读者的借书和换书的过程,时间,书名,读者号码等等信息。对以前的借阅记录有迹可寻。

具体实现

创建读者表:

CREATE TABLE "SCOTT"."READER" 
(
  "LNO" CHAR(12) PRIMARY KEY,
  "RNAME" VARCHAR2(10) NOT NULL,
  "SEX" CHAR(2),
  "BIRTHDAY" DATE,
  "DEPT" VARCHAR2(20),
  "SPEC" VARCHAR2(20),
  "GRADE" CHAR(4),
  "BORNUM" NUMBER(10) DEFAULT 0
)
TABLESPACE "LIBTBS";
ALTER TABLE "SCOTT"."READER" ADD CONSTRAINTS "Sex_CK1" CHECK(Sex BETWEEN '男' AND '女');
ALTER TABLE "SCOTT"."READER" ADD CONSTRAINTS "Bornum_CK2" CHECK(Bornum <= 10);

创建图书表:

CREATE TABLE "SCOTT"."BOOK" 
(
  "ISBN" CHAR(12) PRIMARY KEY,
  "BNAME" VARCHAR2(30) NOT NULL,
  "AUTHOR" VARCHAR2(10),
  "PRESS" VARCHAR2(40),
  "PRICE" NUMBER(7) DEFAULT 0 NOT NULL,
  "CD" CHAR(2) NOT NULL,
  "COPYNUM" NUMBER(10),
  "INVNUM" NUMBER(20),
  "CLASS" VARCHAR2(20) NOT NULL,
CONSTRAINT "CD_CK1" CHECK(CD BETWEEN '有' AND '无')
)
TABLESPACE "LIBTBS";
 
创建借阅表:
CREATE TABLE "SCOTT"."LEND"
(
   "LNO" CHAR(12) REFERENCES "SCOTT"."READER"(LNO),
   "ISBN" CHAR(12) REFERENCES "SCOTT"."BOOK"(ISBN),
   "BarNo" CHAR(10) PRIMARY KEY,
   "Bordate" DATE DEFAULT SYSDATE NOT NULL
)
TABLESPACE "LIBTBS";
  
创建历史借阅表:
CREATE TABLE "SCOTT"."HistoryLend"
(
    "LNO" CHAR(12) REFERENCES "SCOTT"."READER"(LNO),
    "ISBN" CHAR(12) REFERENCES "SCOTT"."BOOK"(ISBN),
    "BarNum" CHAR(10) REFERENCES "SCOTT"."LEND"("BarNo"),
    "Bordate" DATE NOT NULL,
    "Retdate" DATE DEFAULT SYSDATE NOT NULL
)
TABLESPACE "LIBTBS";
ALTER TABLE "SCOTT"."HistoryLend" ADD PRIMARY KEY(LNO,ISBN,"BarNum");

3.视图设计

设计思想

视图可以作为一个特定查询,使用户可以重复使用,在本次综合实验中,我建立了一个查询图书、读者信息和借阅信息的视图,这样不同的操作员就可以直接使用不同的视图来查询,而不是每个人都要输入复杂的select语句
    同时,基于安全考虑,可以针对特定的视图赋给用户权限,而不是给用户赋给一个或几个表的权限,这样可以避免误操作更新数据的不安全因素。

 

具体实现

    创建读者的图书信息查询视图:

CREATE FORCE VIEW "SCOTT"."V_Reader_C1"
AS
SELECT "ISBN","BNAME","AUTHOR","PRESS","INVNUM" FROM "SCOTT"."BOOK"
WITH READ ONLY;
 
创建读者的借阅信息查询视图:
CREATE FORCE VIEW "SCOTT"."V_Reader_C2"
AS
SELECT "LNO","ISBN","BarNo" FROM "SCOTT"."LEND"
WITH READ ONLY;
 
创建图书管理员的借阅信息查询视图:
CREATE FORCE VIEW "SCOTT"."V_Manager_C1"
AS
SELECT * FROM "SCOTT"."LEND"
WITH CHECK OPTION;
 
创建图书管理员的历史借阅信息查询视图:
CREATE FORCE VIEW "SCOTT"."V_Manager_C2"
AS
SELECT * FROM "SCOTT"."HistoryLend"
WITH CHECK OPTION;
 
创建图书管理员的图书信息查询视图:
CREATE FORCE VIEW "SCOTT"."V_Manager_C3"
AS
SELECT * FROM "SCOTT"."BOOK"
WITH CHECK OPTION;
 
 
创建图书管理员的读者信息查询视图:
CREATE FORCE VIEW "SCOTT"."V_Manager_C4"
AS
SELECT "LNO","RNAME","SEX","DEPT","SPEC","GRADE","BORNUM" FROM "SCOTT"."READER"
WITH READ ONLY;

4.索引设计

设计思想

建立一些索引可以用来加速对数据的检索。其实类似于图书前面的目录,你在一本书中找内容时会很耽误时间,所以一般会先看目录,找到感兴趣的条目,而那个条目上是指明内容在那一页的(内容所在的地址),然后就可以迅速找到需要的内容了。

 

具体实现

  1. 在图书表的书名、出版社、作者、价格列是分别创建非唯一索引。
CREATE INDEX index_1 
ON "SCOTT"."BOOK"("BNAME","PRESS","AUTHOR","PRICE");
 
1. 在读者表的读者姓名、所在系部、就读专业列是分别创建非唯一索引。
CREATE INDEX index_2
ON "SCOTT"."READER"("RNAME","DEPT","SPEC");
 
1. 在读者表的借阅数量列上创建一个反键索引。
CREATE INDEX index_3
ON "SCOTT"."READER"("BORNUM") REVERSE;
 
(4)在读者表的性别列上创建一个位图索引。
CREATE BITMAP INDEX index_4
ON "SCOTT"."READER"("SEX");
 
5.存储过程和函数设计
设计思想
存储过程的作用相当于单个表的操作方法,暂且只针对单个表的操作,例如调用存储过程的时候传一个Dept的参数,然后输出满足这个条件的学号和姓名,实现上面功能只调用这个存储过程就行。
函数的创建与存储过程的创建相似,不同之处在于,函数有一个显示的返回值。所以函数里面必须包含一个return语句,来指明函数的返回值,能限定函数返回值的类型,但是无法约束返回值的长度,精度,刻度等。最终也只有一个return背执行。
 
具体实现
建立查询读者信息的存储过程:
当调用该存储过程是传一个Dept的参数,然后就能输出满足这个条件的学号和姓名,这样管理员就可以快速查找到对应学生的信息。
CREATE OR REPLACE PROCEDURE procedure_1(
       p_Deptno "SCOTT"."READER"."DEPT"%TYPE)
AS
       v_Lno "SCOTT"."READER"."LNO"%TYPE,
       v_Rname "SCOTT"."READER"."RNAME"%TYPE;
BEGIN
       DBMS_OUTPUT.PUT_LINE('The reader you found is:');
FOR v_Lno,v_Rname INTO ( SELECT "LNO","RNAME" INTO v_Lno,v_Rname 
FROM "SCOTT"."READER"
WHERE "DEPT"=p_Deptno;)
LOOP
           DBMS_OUTPUT.PUT_LINE(v_Lno||' '||v_Rname);
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
         DBMS_OUTPUT.PUT_LINE('The reader you found is error!!');
END procedure_1;
 
建立查询图书信息的存储过程:
当调用该存储过程是传一个Class的参数,然后就能输出满足这个条件的Isbn号和书名,这样图书管理员就可以快速查找到对应类型的图书信息。
 
CREATE OR REPLACE PROCEDURE procedure_2(
       p_Class "SCOTT"."BOOK"."CLASS"%TYPE)
AS
       v_Isbn "SCOTT"."BOOK"."ISBN"%TYPE,
       v_Bname "SCOTT"."BOOK"."BNAME"%TYPE;
BEGIN
       DBMS_OUTPUT.PUT_LINE('The book you found is:');
FOR v_Isbnv_Bname INTO ( SELECT "ISBN","BNAME" INTO v_Isbn,v_Bname 
FROM "SCOTT"."BOOK"
WHERE "CLASS"=p_Class;)
LOOP
           DBMS_OUTPUT.PUT_LINE(v_Isbn||' '||v_Bname);
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
         DBMS_OUTPUT.PUT_LINE('The book you found is error!!');
END procedure_2;
 
函数的创建:
创建根据学生的学号返回学生平均借书数量的函数:
调用函数并输入学生的学号时,函数计算对应学生的平均借书数量并返回,这样可以大大减少图书管理员的工作量,方便管理员进行统计分析。
CREATE OR REPLACE FUNCTION scott.dept_fun
(v_lno scott.historylend.lno%TYPE,
V_rname OUT scott.reader.rname%TYPE)
Return number
Is
  V_num NUMBER(4);
BEGIN
Select rname into v_rname from scott.historylend
Where lno = v_lno;
Select avg(bornum) into v_num from scott.lend join scott.historylend
On scott.lend.isbn = scott.historylend.isbn
Where scltt.reader.lno = v_lno;
Return v_number
End;
 
6.触发器及包设计
设计思想
触发器的作用很广泛并且在数据库里面的作用也很关键,它的作用是主要实现某种功能(读者借阅量的限制,读者操作权限等等),可以有效的阻拦一些操作并给予相关的提示!也可以用于某些数字的自增或者自减。
包的作用同存储过程差不多,差别在于存储过程只能在单个表中运用,而包却可以在整个库中调用,相当于其权限是很大的!包相当于一个程序里的函数,可以反复调用、灵活性极强,对表的操作也是比较方便与快捷的。
 
具体实现
建立一个触发器,当图书馆的库存量大于复本量时,提示错误,以防止图书管理员的误操作。
CREATE OR REPLACE TRIGGER trigger_book
BEFORE UPDATE ON "SCOTT"."BOOK"
FOR EACH ROW
WHEN("INVNUM">"COPYNUM")
BEGIN
  RAISE_APPLICATION_ERROR(-20001,'The copynumber is lower than collectionnumber!!');
END trigger_book;
 
建立一个触发器,当在借阅表中添加或删除借阅信息时,将读者表中对应读者的借书数量加1或者减1,以防止两者无法对应。
CREATE OR REPLACE TRIGGER trigger_borrow
AFTER INSERT OR DELETE ON "SCOTT"."LEND"
DECLARE
  v_lno "SCOTT"."LEND"."LNO"%TYPE;
BEGIN
IF INSERTING THEN
SELECT "LNO" INTO v_lno FROM "SCOTT"."READER" WHERE "LNO"=:NEW."LNO";
UPDATE "SCOTT"."READER" SET "BORNUM"="BORNUM"+1 WHERE "LNO"=:NEW."LNO";
ELSIF DELETING THEN
SELECT "LNO" INTO v_lno FROM "SCOTT"."READER" WHERE "LNO"=:NEW."LNO";
UPDATE "SCOTT"."READER" SET "BORNUM"="BORNUM"+1 WHERE "LNO"=:OLD."LNO";
END IF;
END trigger_borrow;
 
 
 
7.备份与恢复设计
设计思想
在对Oracle数据库进行备份与恢复设计时,要考虑发生故障后,利用已备份的数据或控制文件,重新建立一个完整的数据库。恢复可以是实例恢复或者是介质恢复,实例恢复是在当oracle实例出现失败后,oracle自动进行的恢复。而介质恢复则是在当存放数据库的介质出现故障时进行恢复。
 
8.数据库安全设计
设计思想
数据库安全设计主要体现在为数据库建立用户,密码,以及不同等级用户的的权限!这样做就可以有效的让不同用户查阅的权限都在管理员的管理下,防止数据的改动和丢失!因此要访问数据库,用户必须指定有效的数据库用户账户,而且还要根据该用户账户的要求成功通过验证,每个数据库用户都有一个唯一的数据库账户。Oracle建议这样做是为了避免潜在的安全漏洞以及为特定的审计活动提供有意义的数据。
在本次综合实验中,我主要创建了Reader和Manager两个角色,分别对应不同的权限,将读者用户加到Reader角色中,将图书管理员用户加到Manager角色中,这样就加强了对数据库的保护。另外,创建概要文件来描述如何使用系统的资源(主要是CPU资源)。将概要文件赋予某个数据库用户,在用户连接并访问数据库服务器时,系统就按照概要文件给他分配资源。
最后,添加审计功能,审计权限的调用记录、用户的dml操作记录、查询操作记录,对行为异常的用户进行判断并警告。另外,用户都只能访问视图而不能直接访问表,这也是数据库安全设计的体现。
 
具体实现
    创建学生用户:
CREATE USER student1
IDENTIFIED BY 123
DEFAULT TABLESPACE USERS
QUOTA 5M ON USERS
PASSWORD EXPIRE;
 
CREATE USER student2
IDENTIFIED BY 123
DEFAULT TABLESPACE USERS
QUOTA 5M ON USERS
PASSWORD EXPIRE;
 
创建图书管理员用户:
CREATE USER manager1
IDENTIFIED BY 123
DEFAULT TABLESPACE USERS
QUOTA 5M ON USERS
PASSWORD EXPIRE;
 
创建角色:
CREATE ROLE student
NOT IDENTIFIED;
CREATE ROLE manager
NOT IDENTIFIED;
 
将角色赋予用户:
GRANT CONNECT,student TO student1;
GRANT CONNECT,student TO student2;
GRANT CONNECT,manager TO manager1;
 
为角色赋予权限:
GRANT SELECT ON "SCOTT"."V_Reader_C1" TO student;
GRANT SELECT ON "SCOTT"."V_Reader_C2" TO student;
GRANT CONNECT,RESOURCE,EXECUTE TO manager;
GRANT SELECT,INSERT,DELETE,UPDATE ON "SCOTT"."V_Manager_C1" TO manager;
GRANT SELECT,INSERT,DELETE,UPDATE ON "SCOTT"."V_Manager_C2" TO manager;
GRANT SELECT,INSERT,DELETE,UPDATE ON "SCOTT"."V_Manager_C3" TO manager;
GRANT SELECT,INSERT,DELETE,UPDATE ON "SCOTT"."V_Manager_C4" TO manager;