广州大学学生实验报告
实验二:数据库管理
此篇分享仅供参考学习,图禁复制,勿作他用!谢谢配合啦!
数据库原理实验之实验二:数据库管理
软件:Oracle SQL Developer
今天实验才刚开始,花几个小时做完了实验二,呼------,舒服啊!要是所有的实验都跟数据库原理实验一样做得这么舒服就好了哈哈!
1、用户权限管理
实验目的:
对ORACLE数据库系统的用户权限管理有感性认识。
实验内容:
理论学习:Oracle权限设置
(基础好的小伙伴可以直接略过理论学习,直接进入实操部分学习!)
一、权限分类:
系统权限:
系统规定用户使用数据库的权限。(系统权限是对用户而言)。
实体权限:
某种权限用户对其它用户的表或视图的存取权限(针对表或视图而言)。
二、系统权限管理:
1、系统权限分类:
DBA:拥有全部特权,是系统最高权限,只有DBA才可以创建数据库结构。
RESOURCE:拥有Resource权限的用户只可以创建实体,不可以创建数据库结构。
CONNECT:拥有Connect权限的用户只可以登录Oracle,不可以创建实体,不可以创建数据库结构。
对于普通用户:授予connect, resource权限。
对于DBA管理用户:授予connect,resource, dba权限。
2、系统权限授权命令:
系统权限只能由DBA用户授出:sys, system(最开始只能是这两个用户)
授权命令:grant connect, resource, dba to 用户名1 [,用户名2]...;
普通用户通过授权可以具有与system相同的用户权限,但永远不能达到与sys用户相同的权限,system用户
的权限也可以被回收。
例:以system用户身份连接数据库之后,执行:
create user cc identified by ccpassword ;
grant resource, connect, DBA to cc;
查询用户拥有哪里权限:
select * from dba_role_privs;
select * from dba_sys_privs;
select * from role_sys_privs;
删除用户: drop user 用户名 cascade;
//加上cascade则将用户连同其创建的东西全部删除
3、系统权限传递:
增加WITH ADMIN OPTION选项,则得到的权限可以传递。
grant connect, resource to CC with admin option; //可以传递所获权限
4、系统权限回收:系统权限只能由DBA用户回收
revoke dba, resource from CC;
5、删除用户
drop user 用户名; //用户没有建任何实体
drop user 用户名 CASCADE; // 将用户及其所建实体全部删除
说明:当前正连接的用户不得删除。
三、实体权限管理
1、实体权限分类:
select, update, insert, alter, index, delete, all //all包括所有权限
execute //执行存储过程权限
user01:
grant select, update, insert on product to user02;
grant all on product to user02;
user02:
select * from user01.product;
// 此时user02查user_tables(连接中能显示的),不包括user01.product这个表,但如果
查all_tables则可以查到,因为他可以访问。all_tables是某一用户所拥有的或有访问权限的表。
user_tables是某一用户所拥有的表。
2. 将表的操作权限授予全体用户:
grant all on product to public;
// public表示是所有的用户,这里的all权限不包括drop。
select owner, table_name from all_tables; // 用户可以查询的表
select table_name from user_tables; // 用户创建的表
select grantor, table_schema, table_name, privilege from all_tab_privs;
// 获权可以存取的表(被授权的)
select grantee, owner, table_name, privilege from user_tab_privs;
// 授出权限的表(授出的权限)
3. DBA用户可以操作全体用户的任意基表(无需授权,包括删除):
DBA用户:
create table stud02.product(id number(10), name varchar2(20));
drop table stud02.emp;
create table stud02.employee as select * from scott.emp;
4. 实体权限传递(with grant option):
user01:
grant select, update on product to user02 with grant option;
// user02得到权限,并可以传递。
5. 实体权限回收:
user01:
revoke select, update on product from user02; //传递的权限将全部丢失。
说明:如果取消某个用户的对象权限,那么对于这个用户使用WITH GRANT OPTION授予权限的用户来说,
同样还会取消这些用户的相同权限,也就是说取消授权时级联的。
正式操作:
1、以SYSTEM身份连接到orcl数据库,创建新的用户并授权(如果原来已有这个用户,可以忽略本步骤):
--system用户中执行下面语句:
create user cc identified by c123;
grant resource, connect, DBA to cc;
--然后新建连接,输入用户名和密码及一些信息后连接。
查询结果如下:(用户cc已成功连接):
2、以用户CC的身份建立连接,并在此连接下执行后面的操作;
select * from user_role_privs;
问:可以看到自己的权限,有多少种权限?
答:看到用户cc有3种权限,分别是connect、resource、DBA。
结果截图:
3、在CC连接中:拷贝代码运行,删去旧的同名数据表(如果是新创建的用户,此步骤可以省略):
--复制下面这段代码执行,可删去旧的同名数据表
Declare
tmp integer default 0;
Begin
select count(*) into tmp from user_tables where table_name='RB';
if(tmp>0) then
execute immediate 'drop table RB';
end if;
select count(*) into tmp from user_tables where table_name='READER';
if(tmp>0) then
execute immediate 'drop table READER';
end if;
select count(*) into tmp from user_tables where table_name='BOOK';
if(tmp>0) then
execute immediate 'drop table BOOK';
end if;
end;
(我是新创建的用户cc,所以省略此步了。)
4、在CC连接中:拷贝代码运行,建立表格及输入数据:
--执行以下语句创建表格并插入一些数据:
create table Reader
(
RNO varchar2(4) primary key,
Rname varchar2(10) not null,
Rsex varchar2(2),
Rage integer,
Rboss varchar2(10),
Raddress varchar2(30)
) ;
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R001','张三',20,'男','李四','416');
create table Book
(
BNO varchar2(4),
Bname varchar2(50) not null,
Bauthor varchar2(50),
Bpress varchar2(50),
Bprice numeric(6,2),
primary key(BNO)
);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B001','严蔚敏','数据结构','清华大学出版社',null);
create table RB
(
RNO varchar2(4),
BNO varchar2(4),
RBdate date default sysdate,
primary key(RNO,BNO),
foreign key (RNO) references Reader(RNO),
foreign key (BNO) references Book(BNO)
);
insert into RB (RNO,BNO) values ('R001','B001');
5、在CC连接中:确认orcl数据库中有这三个数据表,以及相应的数据。
--执行语句:
select * from all_tables where owner='CC' ;
--或者执行:
select * from DBA_tables where owner='CC';
结果均为:
--依次执行语句:
select * from reader;
select * from book;
select * from rb;
相应的数据表:
6、在CC连接中:查询用户CC的权限信息(每句单独执行):
--分别执行下列代码:
select * from dba_role_privs;
select * from dba_sys_privs;
select * from role_sys_privs;
第一句结果截图:
unlimited tablespace表示无限制的表空间权限。
第二句结果截图:
第三句结果:查询得出的表格列出了很多角色及其权限。其中包括DBA、connect、resource。
7、在CC连接中:查询用户创建的表。
select table_name from user_tables;
--查询的是用户cc创建的表的表名table_name
结果:
8、在CC连接中:删去数据表BR,成功吗?
drop table rb;
--结果:脚本输出:Table RB 已删除
--再次执行:
select table_name from user_tables;
问:显示什么结果?
答:RB表已删除,查询结果只有用户cc创建的reader表和book表了。
结果截图:
9、回收用户CC的部分权限:以SYSTEM的身份连接(可以在SQL DEVELOPER的右上角切换),在此连接中执行。
Revoke dba, resource from CC;
--结果:脚本输出:Revoke 成功
--再执行:
select * from user_role_privs;
--查看用户权限,只有connect了。
结果截图:
10、以CC的身份连接数据库(可以在SQL DEVELOPER的右上角选择连接),执行:
create Table Aa(cola int);
问:成功吗?为什么?
答:执行失败!
原因:第9题(即上一步操作)已经回收了用户cc的DBA和resource权限,用户cc已经无权限创建表格了。
结果截图:
11、切换为SYSTEM的连接,执行:
grant resource to CC;
--脚本输出:Grant 成功
12、切换为CC的连接,执行:
select * from user_role_privs;
问:可以看到自己的权限,有多少种权限?
答:用户cc有两种权限:conect和resource。
结果截图:
create Table Aa(cola int);
问:成功吗?为什么?
答:执行成功!因为system用户已经把resource权限授予用户cc了,所以用户cc有权限创建表格了。
13、切换为SYSTEM的连接,执行:
DROP USER CC;
问:成功吗?为什么?
答:断开连接后执行语句,执行失败!
原因:必须指定cascade以删除CC。
结果截图:
14、删除连接CC,在SYSTEM的连接中,执行:
DROP USER CC;
问:成功吗?为什么?
答:断开连接后,执行失败!原因:未指定cascade。
问:怎样才能成功删除用户CC ? 仅仅断开连接就行了吗?
答:不是仅仅断开连接就行,断开连接后,还要执行语句:drop user cc cascade;即在后面加上cascade才可以。
Drop User Cc Cascade;
问:为何要加Cascade ?删去后,还能以用户CC的身份连接吗?
答:因为用户cc创建了一些基本表,在不先删除基本表的前提下想要删除用户cc,即要加cascade才能删除成功。删除后不能以用户cc的身份连接,测试会显示:状态: 失败 -测试失败: ORA-01017: invalid username/password; logon denied,意思是不再连接到oracle。
结果截图:
15、在SYSTEM的连接中,重新创建用户CC和DD:
--执行下列语句:
create user cc Identified By c123;
create user dd identified by d123;
grant resource, connect, DBA to cc,dd;
--查看这两个用户的权限(只有SYSTEM才有权执行下面这条语句):
select * from dba_role_privs where GRANTEE in ('CC','DD');
结果截图:(两个用户均有DBA、resource、connect权限)
16、以CC和DD的身份分别建立连接,使得目前系统加上原来的SYSTEM共有三个连接(为识别方便,连接名和用户名一致)
【说明】连接名为xxe的是system用户,software是导论实验创建的连接,请忽略!
我的连接结果截图:
--选择CC连接,执行:
Create Table from_CC(内容 char(1));
Insert into from_cc values('a');
select * from from_cc;
结果截图:
--选择DD连接,执行:
select owner, table_name from all_tables where table_name='FROM_CC';
问:显示什么?什么意思?
答:执行结果显示如下图,意思:在用户dd可以查询的表中查询表名为FROM_CC的表的创建者owner和表名table_name。
结果截图:
select * from from_cc;
问:显示什么?什么意思?
答:显示下图:表或视图不存在。意思:在用户dd中无法查询到表from_cc的数据信息。因为表from_cc在用户cc中创建的,且用户cc并未授权给用户dd。
结果截图:
--选择CC连接,执行:
grant all on from_cc to dd;
--脚本输出:Grant 成功
--选择DD连接,执行:
select owner, table_name from all_tables where table_name='FROM_CC';
问:显示什么?什么意思?
答:显示下图。意思:在用户dd中查询的表中查询表名为from_cc的表的创建者owner和表名table_name。
结果截图:
select * from from_cc;
问:显示什么?
答:显示下图
结果截图:
select * from cc.from_cc;
问:显示什么?怎么回事?
答:显示下图。解释:虽然用户cc把对from_cc表的all操作权限授予用户dd了,但这个表终究还是用户cc创建的,所以,欲在用户dd中查询from_cc表的数据,则要显示地执行select * from cc.from_cc;,指明from_cc的创建用户。
问:刷新DD连接下的表,有没有“FROM_CC”这个表?
答:没有!用户dd只是获得了对表from_cc的all权限,但其连接下的表并不会有from_cc。
--选择DD连接,执行:
Insert into cc.from_cc values('d');
select * from cc.from_cc;
问:插入成功了吗?
答:貌似插入成功了!
结果截图:
【注意】此处没有commit;提交插入的数据,所以在用户cc中查询表from_cc的数据时不会显示'd'的。
16、选择CC连接,执行:
Revoke insert on FROM_CC from DD;
--执行后,收回用户dd对from_cc表的插入权限。
--选择DD连接,执行:
select * from cc.from_cc;
问:能显示表的内容吗?
答:能显示表的内容。
Insert into cc.from_cc values('y');
select * from cc.from_cc;
问:插入成功了吗?
答:貌似插入成功了。
结果截图:
【注意】此处没有commit;提交插入的数据,所以在用户cc中查询表from_cc的数据时不会显示’d’的。
--选择SYSTEM连接,执行:
Revoke dba, resource from DD;
--脚本输出:Revoke 成功
--选择DD连接,执行:
select * from cc.from_cc;
问:能显示表的内容吗?
答:能显示from_cc表的内容。
Insert into cc.from_cc values('z');
select * from cc.from_cc;
问:插入成功了吗?
答:貌似插入成功!
结果截图:
【注意】此处没有commit;提交插入的数据,所以在用户cc中查询表from_cc的数据时不会显示'd'的。
--选择CC连接,执行:
Revoke all on FROM_CC from DD; --回收用户dd对from_cc表的all权限
select * from cc.from_cc;
--结果:此处没有显示前面插入的'd'、'y'、'z'。
结果截图:
--选择DD连接,执行:
select * from cc.from_cc;
--结果:显示前面插入的全部数据。
结果截图:
17、删除连接DD后,重新添加连接DD。
select * from cc.from_cc;
--显示这个数据对象不存在。
结果截图:
select * from user_role_privs;
问:当前用户有多少种权限?
答:当前用户只有一种权限:connect。
结果截图:
create Table from_DD(哦 char(2));
问:能执行吗?
答:不能。因为用户dd只有connect权限,无法创建表格的。
结果截图:
--选择SYSTEM连接,执行:
grant resource to dd;
--脚本输出:Grant 成功
--选择DD连接,执行:
Create Table from_DD(哦 char(2));
问:能执行吗?
答:不能。
结果截图:
--删除连接DD后,重新添加连接DD
Create Table from_DD(哦 char(2));
Insert into from_dd values('甲');
select * from from_dd;
问:能看到记录“甲”吗?
答:能看到记录“甲”!
结果截图:
--选择CC连接,执行:
select * from dd.from_dd;
问:能看到记录“甲”吗?
答:不能看到。
结果截图:
问:用户CC怎样才能看到from_dd表的所有记录?用户CC怎样才能为from_dd表添加记录?
答:
--选择dd连接,执行语句:
grant all on from_dd to cc;
--然后在cc连接中执行:
select * from dd.from_dd;
--便可看到记录“甲”了。在用户cc中执行语句:
insert into dd.from_dd values('d');
--为表from_dd插入数据后执行:
commit;
--提交后,就成功为表from_dd添加记录了。
在用户dd中查询即可看到刚添加的数据:
2、Oracle数据库对象
实验目的
Oracle 数据库包含许多数据库对象,例如表、视图、索引、序列、存储过程、触发器等。表、视图、索引的操作在前面的实验中已经做了相应的练习,本实验将介绍如何使用序列、触发器和存储过程。同学们可以通过本实验掌握如何定义、使用删除这些数据库对象。
实验内容
- 序列
a) 创建序列
b) 查看创建的序列对象
c) 使用序列
d) 修改序列
e) 删除序列 - 存储过程
a) 创建三个数据表
b) 插入数据创建存储过程
c) 创建存储过程,更新表中的数据
d) 执行存储过程,并比较存储过程执行前后的数据变化情况
e) 删除存储过程
f) 创建存储过程
g) 运行存储过程 - 触发器
a) 创建触发器
b) 创建触发器credit_id
c) 查看刚创建的触发器对象
d) 激活刚创建的触发器
1、以SYSTEM连接数据库ORCL,执行以下语句查看对象:
select object_name,owner from all_objects where owner = 'SYSTEM';
问:显示有多少行?
答:显示有529行。
结果截图:
2、创建新的用户并授权:
create user cc identified by c123;
grant resource, connect, DBA to cc;
--此处我先执行drop user cc cascade;删除了之前的用户,再新建用户cc
3、以用户CC的身份建立连接,并在此连接下执行【序列】的操作:
select object_name,owner from all_objects where owner = 'SYSTEM';
问:显示有多少行?
答:显示有503行。
结果截图:
select object_name,owner from all_objects where owner = 'CC';
问:显示有多少行?
答:显示0行。
结果截图:
--执行:
create sequence my_seq_01 increment by 1 start with 1 nomaxvalue nocycle;
create sequence my_seq_02 increment by 2 start with 1;
select object_name,owner from all_objects where owner = 'CC';
问:显示有多少行?
答:显示有2行。
结果截图:
select object_name,Object_Type, owner from all_objects where owner = 'SYSTEM' and
OBJECT_TYPE='SEQUENCE';
问:显示有多少行?
答:显示有20行。
结果截图:
Select Object_Name, Object_Type, Owner From All_Objects Where Owner = 'CC' and
OBJECT_TYPE='SEQUENCE';
问:显示有多少行?
答:显示有2行。
结果截图:
select my_seq_01.nextval from dual;
--dual是一个虚拟表,用来构成select的语法规则
问:重复执行上面的这条语句,得到什么序列?
答:结果是下图中的nextval列中数字从1开始,每执行一次语句就增加1。序列是1,2,3,4,5,
6,7,8,9,10,11,12,…
结果截图:
alter sequence my_seq_01 increment by 10 ;
select my_seq_01.nextval from dual;
问:重复执行上面的这条语句,得到什么序列?
答:结果是下图中的nextval列中数字从上次的12开始,每执行一次语句就增加10。序列是22,32,42,
52,62,…
结果截图:
select my_seq_02.nextval from dual;
问:重复执行上面的这条语句,得到什么序列?
答:结果是下图中的nextval列中数字从1开始,每执行一次就增加2。序列是1,3,5,7,9,11,13,…
结果截图:
drop sequence my_seq_02;
--脚本输出:Sequence MY_SEQ_02已删除
select my_seq_02.nextval from dual;
问:什么结果?
答:结果如下图:
create sequence my_seq_02 increment by 3 start with 100;
select my_seq_02.nextval from dual;
问:重复执行上面的这条语句,得到什么序列?
答:结果是下图中的nextval列中数字从100开始,每执行一次就增加3。序列是100,103,106,109,112,115,118,…
结果截图:
4、 在CC的连接中,执行【存储过程】的操作;
--复制执行下面第一段代码,删去同名数据表
Declare
tmp integer default 0;
Begin
select count(*) into tmp from user_tables where table_name='SC';
if(tmp>0) then
execute immediate 'drop table SC ';
end if;
select count(*) into tmp from user_tables where table_name='STUDENT';
if(tmp>0) then
execute immediate 'drop table STUDENT ';
end if;
select count(*) into tmp from user_tables where table_name='COURSE';
if(tmp>0) then
execute immediate 'drop table COURSE ';
end if;
Select count(*) into tmp From All_Objects Where OBJECT_NAME='SC_INS' and OBJECT_TYPE='PROCEDURE';
if(tmp>0) then
execute immediate 'drop PROCEDURE SC_INS ';
end if;
Select count(*) into tmp From All_Objects Where OBJECT_NAME='STUDENT_NO' and OBJECT_TYPE='SEQUENCE';
if(tmp>0) then
execute immediate 'drop SEQUENCE STUDENT_NO ';
end if;
end;
--脚本输出:PL/SQL 过程已成功完成。
--然后第二段语句,重新创建数据表:
create table student(sno int primary key, sname varchar(8));
create table course(cno int primary key, cname varchar(10));
create table sc(sno int, cno int, grade int,
primary key(sno,cno),
foreign key (sno) references student(sno), foreign key (cno) references course(cno));
问:成功了吗?上面的三个表的创建顺序能否任意调整?
答:成功了!不能任意调整!student表和course表的创建顺序可以任意调整,但sc表必须是在student表和course表创建后才能创建,因为sc表的rno和cno属性参照的分别是student表的rno属性和course表的cno属性。
select object_name, Object_Type, owner from all_objects where owner = 'CC';
问:显示有多少行?索引是怎么产生的?
答:显示有8行,有两个序列、三个表格和三个索引,如下图。索引产生:我的理解是数据库管理系统在执行建表语句时自动生成了由主码来确定的索引。
结果截图:
到SQL DEVELOPER的可视化窗口查看student表的索引信息如图:
问:查看SC表的索引,有哪些列来确定?依据是什么?索引名是什么?
答:Sc表索引如下图: 由sno、cno列来确定,依据是主键,索引名是SYS_C0011428。
create sequence student_no increment by 1 start with 2012001;
insert into student values(student_no.nextval, 'aaaaaa');
insert into student values(student_no.nextval,'bbbbbbb');
insert into student values(student_no.nextval,'ccccccc');
insert into student values(student_no.nextval,'ddddddd');
commit;
select * from student;
--查看student表的内容
结果截图:
insert into course values (105,'程序设计');
insert into course values (908,'大学英语');
insert into course values (433,'数据结构');
commit;
select * from course;
--查看course表的内容
结果截图:
create procedure sc_ins(ino int,cno int,grade int) is
begin
if(grade>=0) then insert into sc values (ino,cno,grade);
else insert into sc values (ino,cno,null);
end if;
end;
问:成功了吗? 显示什么内容?
答:成功了,脚本输出:procedure SC_INS 已编译,
select Object_Name, Object_Type, Owner From All_Objects Where Owner = 'CC' and
OBJECT_TYPE='PROCEDURE';
问:显示有多少行?
答:显示有1行。
结果截图:
exec sc_ins (2012001,105,60);
exec sc_ins (2012001,908,0);
exec sc_ins (2012001,433,98);
exec sc_ins (2012002, 105,75);
exec sc_ins (2012002, 433,-1);
exec sc_ins (2012003, 105,64);
exec sc_ins (2012003, 908,90);
exec sc_ins (2012003, 433,-100);
问:成功了吗?
答:后面五行成功了,前面三行失败!因为前面三行中的SNO:2012001在student表中找不到父项关键字,
违反了完整约束条件。而后面五行数据满足要求,执行显示PL/SQL过程成功完成。
结果截图:
select student.sno,sname,cname,grade
from student,course,sc
where student.sno=sc.sno and course.cno=sc.cno;
问:显示结果说明,成绩为负数的话,在数据表里是什么内容?存储过程有什么好处?
分数为0,和分数为负数,有区别吗?
答:显示结果说明,成绩为负数的话,在数据表里的内容是空值(null)。
存储过程的好处:
1、存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就
编译一次,所以使用存储过程可提高数据库执行速度。
2、存储过程可以重复使用,可减少数据库开发人员的工作量。
分数为0和分数为负数有区别!
区别:
--执行语句:
exec sc_ins (2012005, 433,0);
/*然后再执行上面的查询语句,可以发现分数为0的话在数据表里的内容就是0,而不是像分数为负数时在
数据表里的内容一样为空值(null),这跟前面的procedureSC_INS的编译语句有关。*/
结果截图:
5、在CC的连接中,执行触发器的操作;
--触发器只影响当前表:
alter table sc add (gradelevel char(1));
--脚本输出:Table SC 已变更
update sc set gradelevel='A' where grade>=85;
update sc set gradelevel='B' where grade>=75 AND grade<85;
update sc set gradelevel='C' where grade>=60 AND grade<75;
update sc set gradelevel='D' where grade<60;
--脚本输出四个:1行已更新
select student.sno,sname,cname,grade,gradelevel
from student,course,sc
where student.sno=sc.sno and course.cno=sc.cno;
问:看到和上一步的显示结果有何区别?
答:可以看到之前的分数已经变成了对应的A、B、C、D。
结果截图:
create or replace trigger sc_ins before insert or update on sc
for each row
begin
if :new.grade>=85 then :new.gradelevel:='A';
else if :new.grade>=75 then :new.gradelevel:='B';
else if :new.grade>=60 then :new.gradelevel:='C';
else if :new.grade>=60 then :new.gradelevel:='D';
end if;
end if;
end if;
end if;
end;
问:执行成功了吗?
答:执行成功了!脚本输出:Trigger SC_INS。
--依次执行:
select * from sc where sno=2012002;
insert into sc(sno,cno,grade) values (2012002,908,80);
select * from sc where sno=2012002;
三条语句结果截图:
问:刚刚插入的行,gradelevel列的值(B)哪里来的?
答:我认为是触发器的作用,前面的语句意思是插入或更新SC表每一行之前先创建或更新触发器trigger_ins,然后就是根据要插入的分数得到对应的A或B或C或D,即gradelevel列的值。然后再插入数据,查询数据时会发现gradelevel列的值已经是对应的字母了。
alter table course add (maxgrade int);
update course set maxgrade=0;
select * from course;
问:表的结构改变成功了吗?修改成功没有?
答:表的结构已经改变,修改成功了!
结果截图:
create or replace trigger course_ins before insert or update on sc
for each row
declare oldg int;
begin
select maxgrade into oldg from course where cno=:new.cno;
if oldg<:new.grade then update course set maxgrade=:new.grade where cno=:new.cno;
end if;
end course_ins;
问:触发器生成成功了吗?当前触发器的目录下有多少项?
答:触发器生成成功了,脚本输出:Trigger COURSE——INS 已编译。当前触发器的目录下有2项:COURSE_INS和SC_INS。
结果截图:
--执行:
select * from course;
记下当前各科的最高分数。
答:上面的update course set maxgrade=0;设置了maxgrade属性列的值全为0。
insert into sc(sno,cno,grade) values (2012004,908,99);
insert into sc(sno,cno,grade) values (2012004,433,88);
insert into sc(sno,cno,grade) values (2012004,105,59);
select * from sc;
select * from course;
问:2012004号同学的三科分数插入成功了吗?
当前各科的最高分有没有变化?
答:从上面直接顺着执行下来,刚开始报错了:
SQL 错误: ORA-04098: 触发器 'CC.COURSE_INS' 无效且未通过重新验证。
然后我重新执行了创建触发器的代码,然后2012004号同学的三科分数就插入成功了,查询后得知当前各科最高分发生了变化。
结果截图:
select * from sc where sno=2012003 and cno=105;
问:2012003号同学的105号课程的分数是多少?级别是什么?
答:2012003号同学的105号课程的分数是64,级别是C,
结果截图:
update sc set grade=100 where sno=2012003 and cno=105;
select * from sc where sno=2012003 and cno=105;
select * from course;
问:2012003号同学的105号课程的分数修改成功了吗?级别(sc.gradelevel)有没有相应变化?当前各科的最高分(course.maxgrade)有没有变化?
一个修改语句,可以同时触发两个表的数据改变吗?
答:2012003号同学的105号课程的分数修改成功了! 级别(sc.gradelevel)也相应变化了,变成了“A”,当前各科的最高分(course.maxgrade)也改变了。
所以由上分析可得:一个修改语句可以同时出发两个表的数据改变。
结果截图:
补充知识:
语句级触发器:
在默认情况下创建的DML 触发器为语句级触发器,即触发事件发生后,触发器只执行一次。在语句级触发
器不能对列值进行访问和操作,也不能获取当前行的信息如果触发器响应多个DML 事件,而且需要根据事件
的不同进行不同的操作,则可以在触发器体中使用3 个条件谓词,即INSERTING、UPDATING、DELETING。
行级触发器:
行级触发器是指执行DML 操作时,每操作一个记录,触发器就执行一次,一个DML操作涉及多少个记录,
触发器就执行多少次。在行级触发器中可以使用WHEN 条件,进一步控制触发器的执行。在行级触发器中引入
了:old 和:new 两个标识符,来访问和操作当前被处理记录中的数据。:old 和:new 是DML 语句对应表的
行记录类型。在不同触发事件中,:old 和:new 的意义不同。在执行部分引用使用:old.field
和:new.field,在WHEN 条件中使用则不带冒号。
3、数据备份与恢复
实验目的
掌握ORACLE数据库系统的一种备份/恢复方法。
实验内容
1、在orcl数据库中创建新的用户并授权(如果原来已有这个用户,可以忽略本步骤):
create user cc identified by c123456 ;
grant resource, connect, DBA to cc;
2、以用户CC的身份建立连接,并在此连接下执行后面的操作;
3、拷贝代码运行,删去旧的同名数据表:
Declare
tmp integer default 0;
Begin
select count(*) into tmp from user_tables where table_name='RB';
if(tmp>0) then
execute immediate 'drop table RB';
end if;
select count(*) into tmp from user_tables where table_name='READER';
if(tmp>0) then
execute immediate 'drop table READER';
end if;
select count(*) into tmp from user_tables where table_name='BOOK';
if(tmp>0) then
execute immediate 'drop table BOOK';
end if;
end;
脚本输出:PL/SQL过程已成功完成。
4、拷贝代码运行,建立表格及输入数据:
create table Reader
(
RNO varchar2(4) primary key,
Rname varchar2(10) not null,
Rsex varchar2(2),
Rage integer,
Rboss varchar2(10),
Raddress varchar2(30)
) ;
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R001','张三',20,'男','李四','416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R002','张三',35,'女',null,'417');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R003','李四',30,'男',null,'416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R004','王五',20,'男',null,'417');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R005','马六',40,'男',null,'416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R006','刘三',20,'男',null,'417');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R007','王四',40,'男','李四','416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R008','李小龙',20,'男','李四','417');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R009','王小倩',40,'男','李四','416');
insert into Reader (RNO,Rname,Rage,Rsex,Rboss, Raddress) values('R010','王一小',20,'男','李四','417');
create table Book
(
BNO varchar2(4),
Bname varchar2(50) not null,
Bauthor varchar2(50),
Bpress varchar2(50),
Bprice numeric(6,2),
primary key(BNO)
);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B001','严蔚敏','数据结构','清华大学出版社',null);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B002','唐发根','数据结构','北航出版社',24);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B003','王珊','数据库原理','高等教育出版社',40);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B004','张飞','数据库原理','清华大学出版社',30);
insert into book (BNO,Bauthor,Bname, bpress, bprice) values('B005','王珊','数据库原理','清华大学出版社',null);
create table RB
(
RNO varchar2(4),
BNO varchar2(4),
RBdate date default sysdate,
primary key(RNO,BNO),
foreign key (RNO) references Reader(RNO),
foreign key (BNO) references Book(BNO)
);
insert into RB (RNO,BNO) values ('R001','B001');
insert into RB (RNO,BNO) values ('R001','B002');
insert into RB (RNO,BNO) values ('R001','B004');
insert into RB (RNO,BNO) values ('R002','B001');
insert into RB (RNO,BNO) values ('R003','B001');
insert into RB (RNO,BNO) values ('R004','B001');
insert into RB (RNO,BNO) values ('R004','B002');
insert into RB (RNO,BNO) values ('R005','B001');
insert into RB (RNO,BNO) values ('R006','B001');
insert into RB (RNO,BNO) values ('R006','B003');
insert into RB (RNO,BNO) values ('R006','B005');
insert into RB (RNO,BNO) values ('R006','B002');
insert into RB (RNO,BNO) values ('R006','B004');
5、以CC的身份连接,确认orcl数据库中有这三个数据表,以及相应的数据。
--执行语句:
select * from all_tables where owner='CC' ;
--或者:
select * from DBA_tables where owner='CC';
结果截图:
--依次执行语句:
select * from reader;
select * from book;
select * from rb;
结果截图:
6、打开“Database Configuration Assistant”
【说明】创建数据库操作和导出操作按下面一系列图操作即可,每张图操作完,然后点击下一步就好,或有的图是直接点击下一步。
输入数据库名“mydb”:
(这里名字任意,自己记住就好!)
【注意】输入口令,确认口令,记住口令!
【说明】我前一步按口令要求设置了,因此不会有弹窗警告(口令长度至少为8个字符,口令必须包含至少一个大写字母,一个小写字母和一个数字)。不过,根据以前的经验来说,这里不必理会直接点击“是”也OK的,应该问题不大,个人觉得口令如此要求主要是为了安全吧。
如果不放心那就点击“否”,然后重设。
【说明】前面已选择“所有账户使用同一管理命令”,此处点击退出即可。
至此数据库创建完成了!
回到Oracle SQL Developer软件界面继续进行下面的操作:
7、确认F盘有文件“导出.sql”
确认截图如下:
双击打开【导出.sql】,有些长,这里只展示头尾一些代码以便确认。
8、到ORACLE SQL DEVELOPER中以SYSTEM用户的身份建立新的连接(这个密码是前面自己新建数据库输入的密码):
以system身份建立新的连接,密码是刚刚创建数据库时设置的。测试:成功,点击连接即可成功连接。
结果截图:
9、在该连接下执行以下语句,即在数据库MYDB里增加用户CC,以便与备份的用户名一致(打开文件“导出.sql”可见里面的语句带了用户名):
create user cc identified by c123456;
grant resource, connect, DBA to cc;
10、以用户CC的身份建立新的连接到数据库mydb:
用户名输入cc,密码c123456,测试成功,SID(I)输入mydb,点击连接即可。
结果截图:
11、 确认mydb中没有数据表READER、BOOK、RB:
执行语句:select * from all_tables where table_name='READER' or table_name='BOOK'
or table_name='RB';
显示结果确认:mydb中没有数据表READER、BOOK、RB
结果截图:
(此处直接在mydbsystem连接中看也可。)
12、在MYDB的CC用户连接中打开文件(或用记事本打开再复制粘贴)运行。
打开记事本文件复制粘贴在mydb的cc用户(连接名为ccmydb)连接中,并运行。
结果截图:
13、确认MYDB中含有这三个表,且表的内容、约束等与数据库ORCL中的一致。
确认MYDB中含有这三个表,结果截图:
三个表的详细数据如下:
三个表的约束条件如下:
通过查看表的各种信息可知:MYDB中含有reader、book、rb这三个表,且表的内容、约束等与数据库ORCL中
的一致!
14、为避免占用太多的系统资源,删去数据库MYDB。先删去有关MYDB的所有连接。
首先删除system身份的连接和连接名为ccmydb的用户cc,其中一个结果截图:
【说明】如果按照上述步骤,应该有两个连接:SYSTEM用户的连接和CC用户的连接。
15、 打开“Database Configuration Assistant”
16、删去数据库MYDB:
【注意】如果未删除数据库的所有连接,则无法删除数据库。
补充知识:
Oracle数据库有三种标准的备份方法:
1、导出/导入
2、热备份(被备份的数据库不必关闭)
3、冷备份(被备份的数据库必须关闭)
导出备件是一种逻辑备份,冷备份和热备份是物理备份。
我们这里做的属于逻辑备份。物理备份是指文件级的备份,有兴趣的小伙伴可以查阅ORACLE的有关手册。
4、事务管理
实验目的
事务是由用户定义的一个数据库的操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。 Oracle数据库使用事务机制来确保数据的一致性,数据库的事务机制是发生在第一个SQL语句执行时,结束于COMMIT或ROLLBACK命令执行时。只有一个事务执行完成后,另一个可执行的SQL语句才能执行。SQL执行时,所有的数据改变都是暂时的,只有结束事务的时候,才会真正写入数据库。
通过本实验,对事务管理有感性认识。
实验内容
1、用帐号sys密码oracle创建新的用户并授权:
先以sys的身份建立连接:
--执行语句:
create user cc identified by ccc ;
grant resource, connect, DBA to cc;
--然后点击新建连接:输入对应信息,点击连接即可成功连接。
2、以用户CC的身份建立连接,并在此连接下执行下面的操作;
create table mytable(tno char(2) primary key, tname char(8));
--脚本输出:Table MYTABLE 已创建。
3、 拷贝代码运行,建立表格及输入数据:
insert Into Mytable Values('01','赵老大');
select * from mytable;
insert Into Mytable Values('02','赵老二');
select * from mytable;
insert Into Mytable Values('03','赵老三');
select * from mytable;
问:表中共有多少行数据?
答:mytable表中一共3行数据。
结果截图:
insert Into Mytable Values('04','钱老大');
select * from mytable;
insert Into Mytable Values('05','钱老二');
select * from mytable;
rollback;
select * from mytable;
问:回退到哪里?表中剩下多少行数据?
答:回退到建表之后,插入数据之前,表中没有任何之前插入的数据了,即剩下0行数据。
结果截图:
insert Into Mytable Values('01','赵老大');
select * from mytable;
insert Into Mytable Values('02','赵老二');
select * from mytable;
insert Into Mytable Values('03','赵老三');
select * from mytable;
commit;
insert Into Mytable Values('04','钱老大');
select * from mytable;
insert Into Mytable Values('05','钱老二');
select * from mytable;
rollback;
select * from mytable;
问:回退到哪里?表中剩下多少行数据?commit的作用是什么?
答:回退到提交前面三条数据之后,插入“钱老大”数据之前,表中还剩下3行数据。
commit的作用:commit是提交的意思,此处对insert适用,作用是如果插入数据的时候出现错误,
可以执行rollback;进行回退,如果只想回退到出现错误的那一步之前,即只回退一步,那在插入数据时
就要注意执行commit;提交,commit以后就不能回退了。
结果截图:
insert Into Mytable Values('04','钱老大');
Savepoint p1;
select * from mytable;
insert Into Mytable Values('05','钱老二');
Savepoint p2;
select * from mytable;
insert Into Mytable Values('06','钱老三');
select * from mytable;
rollback to p2;
select * from mytable;
rollback to p1;
select * from mytable;
问:运行结果显示,Savepoint的作用是什么?
答:运行结果显示如下图:
Savepoint的作用:意为保存点,保存点是事务中的一点。用于取消部分事务,当结束事务时,会自动的删除
该事务中所定义的所有保存点。当执行rollback时,通过指定保存点可以回退到指定的点,然后就可以接着
指定的点后续的操作执行了。
结果截图:
实验二:数据库管理----实验报告分享就到此为止啦,分享的同时加深了自己的理解和记忆,希望也能帮到大家,如有错漏欢迎大家来纠正与补充,谢谢!
欲浏览更多?欢迎到访---->大白的博客,多多支持咯!
转载:https://blog.csdn.net/weixin_44723488/article/details/106267059