Oracle数据库实验操作复习

应用案例分析

表空间

一. 表空间的空间大小估算
假设某业务系统有两张表(客户表cust和交易记录表deal)需要存储在同一个表空间tbs中,客户数量500万,按照平均每个客户每天保存1个交易记录,系统保存最近100天交易数据:

客户表cust

列名 类型 存储长度
客户编号 字符 8字节
客户姓名 字符 30字节
联系电话 字符 12字节

交易记录表deal

列名 类型 存储长度
交易序号 数字,自增 8字节
客户编号 字符 8字节
交易时间 日期 10字节
数量 数字 4字节
产品名称 字符 20字节
  1. 表空间tbs需要多大存储空间(写出估算过程)?
cust:50*5000000=250 000 000=250M
deal:50*5000000*100=25G
  1. 假设数据文件最大32G,写出创建表空间tbs的SQL语句。
总量:25.25G
create tablespace tbs
datafile '/u01/..../tbs01.dbf'
size 2G autoextend on next 100M;

假设估算后40G,大于单个文件大小
create tablespace tbs
datafile 
'/u01/..../tbs01.dbf' size 2G autoextend on next 100M,
'/u01/..../tbs02.dbf' size 2G autoextend on next 100M;

二. 根据如下错误信息,分析并提出解决方案
错误信息如下:
insert into t01 select * from dba_objects

错误报告

SQL 错误: ORA-01653: 表 T01 无法通过 128 (在表空间 TBS1 中) 扩展  
01653. 00000 -  "unable to extend table %s.%s by %s in tablespace %s"  
*Cause:    Failed to allocate an extent of the required number of blocks for  
           a table segment in the tablespace indicated.  
*Action:   Use ALTER TABLESPACE ADD DATAFILE statement to add one or more  
           files to the tablespace indicated.  

select * from dba_data_files;

create tablespace tbs1
datafile '/u01/app/oracle/oradata/MYDB/tbs101.dbf' size 10M;

select count(*) from dba_objects;

create table t01 tablespace tbs1 as select * from dba_objects;

insert into t01 select * from dba_objects;

  • 解决办法:
  1. 判断原表空间文件是否自动扩展,如果不是可开启自动扩展
select * from dba_data_files;
alter database datafile '/u01/app/oracle/oradata/MYDB/tbs101.dbf'
autoextend on next 100M;
  1. 初始已自动扩展,增加文件
alter tablespace tbs1 add datafile 
'/u01/app/oracle/oradata/MYDB/tbs102.dbf' autoextend on next 100M;

用户权限

select * from dba_data_files;
create tablespace tbs2 datafile
'/u01/app/oracle/oradata/MYDB/tbs201.dbf'
size 100m autoextend on next 100m;

drop tablespace tbs2 including contents and datafiles;

create user u01 identified by u01 default tablespace tbs2;

drop user u01 cascade;

SQL>quit

一. 根据如下错误信息,分析并提出解决方案
连接数据库时遇到错误:

$ sqlplus u01/u01  
ERROR:  
ORA-01045: user U01 lacks CREATE SESSION privilege; logon denied  

原因分析:用户缺少create session权限
解决:以管理员身份给用户u01授予权限
grant create session to u01;

二. 根据如下错误信息,分析并提出解决方案
创建表时遇到错误信息如下:

$ sqlplus u01/u01
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0
SQL> create table t01(id int);
create table t01(id int)
*
ERROR at line 1:
ORA-01031: insufficient privileges

原因分析:缺少create table权限
解决:以管理员身份给用户u01 授予权限
grant create table to u01;

三. 根据如下错误信息,分析并提出解决方案
插入数据时遇到错误信息如下:

$ sqlplus u01/u01
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0
SQL> create table t01(id int);
Table created.
SQL> insert into t01 values(1);
insert into t01 values(1)
            *
ERROR at line 1:
ORA-01950: no privileges on tablespace 'TBS1'

原因分析:在表空间tbs1没有空间使用权限
解决:以管理员身份给用户U01分配空间使用权
alter user u01 quota unlimited on tbs2;

实验二、逻辑结构操作

  1. 创建一个表空间mytbs,数据文件/u01/app/oracle/oradata/MYDB/mytbs01.dbf,初始大小10M,自动扩展,每次扩2M,写出创建语句。
    create tablespace mytbs datafile '/u01/app/oracle/oradata/MYDB/mytbs01.dbf' size 10M autoextend on next 2M;
    create undo tablespace myundo datafile '/u01/app/oracle/oradata/MYDB/myundo01.dbf' size 10M autoextend on next 1M;

  2. 修改表空间mytbs,增加两个数据文件/u01/app/oracle/oradata/MYDB/mytbs02.dbf和/u01/app/oracle/oradata/MYDB/mytbs03.dbf,大小20M,写出修改语句。
    alter tablespace tbs add datafile '/u01/app/oracle/oradata/MYDB/tbs02.dbf' size 50M autoextend on next 10M;

  3. 创建一个临时表空间mytmp,数据文件/u01/app/oracle/oradata/MYDB/mytmp01.dbf,初始大小20M,自动扩展,每次扩5M,写出创建语句。
    create TEMPORARY TABLESPACE mytmp tempfile '/u01/app/oracle/oradata/MYDB/mytmp01.dbf' size 20M autoextend on next 5M;

  4. 查询所有表空间信息(查询dba_tablespaces),写出查询语句。
    select * from dba_tablespace

  5. 查询mytbs表空间包含哪些数据文件(查询dba_data_files),要求只查询mytbs表空间,写出查询语句。
    SELECT file_name FROM dba_data_files WHERE tablespace_name = 'MYTBS';'

  6. 删除表空间mytm
    drop tablespace mytm including contents and datafiles;

实验三、用户权限

  1. 创建一个持久表空间mytbs1,数据文件/u01/app/oracle/oradata/MYDB/mytbs101.dbf,初始大小50M,自动扩展,每次扩10M。
    create tablespace mytbs1 datafile '/u01/app/oracle/oradata/MYDB/mytbs101.dbf' size 50M AUTOEXTEND ON next 10M;

  2. 创建一个持久表空间mytbs2,数据文件/u01/app/oracle/oradata/MYDB/mytbs201.dbf,初始大小50M,自动扩展,每次扩10M。
    create tablespace mytbs2 datafile '/u01/app/oracle/oradata/MYDB/mytbs201.dbf' size 50M AUTOEXTEND ON next 10M;

  3. 创建一个临时表空间mytmp1,临时文件/u01/app/oracle/oradata/MYDB/mytmp101.dbf,初始大小50M,自动扩展,每次扩1M。
    create temporary tablespace mytmp1 tempfile '/u01/app/oracle/oradata/MYDB/mytmp101.dbf' size 50M AUTOEXTEND on next 1M;

  4. 创建用户u01,密码u01,默认持久表空间mytbs1,默认临时表空间mytmp1
    create user u01 identified by u01 default tablespace mytbs1 temporary tablespace mytmp1;

  5. 修改用户u01,指定可以使用表空间mytbs1,没有最大限度
    alter user u01 quota unlimited on mytbs1;

  6. 修改用户u01,指定可以使用表空间mytbs2,最大限度20M
    alter user u01 quota 20M on mytbs2;

  7. 修改用户u01密码,改成x01
    alter user u01 identified by x01;

  8. 授予u01创建会话、创建表权限
    grant create session,create table to u01;

  9. 查询用户u01具备哪些系统权限
    select * from dba_sys_privs where grantee='U01';

  10. 删除用户u01
    drop user u01 cascade;

实验四、表基本操作

按照下面表格信息写出创建表的语句
部门表 tbldept

字段 类型 说明
deptid number(5) 部门编号
deptname varchar2(30) 部门名称

员工表 tblemp

字段 类型 说明
empid number(5) 员工编号
empname varchar2(10) 员工名称
deptid number(5) 部门编号

create table tbldept(deptid number(5),deptname varchar2(30));
create table tblemp(empid number(5),empname varchar2(20),deptid number(5));

  1. 按照下面要求分别写出修改表结构的语句

    • 修改表tblemp,增加列phone,类型varchar2(20)
      alter table tblemp add phone varchar2(20);
    • 修改表tblemp,增加列age,类型number
      alter table tblemp add age number;
    • 修改表tblemp,增加列gender,类型varchar2(10)
      alter table tblemp add gender varchar2(10);
    • 修改表tblemp,将列empname类型修改为varchar2(20)
      alter table tblemp modify empname varchar2(20);
    • 修改表tblemp,删除列phone
      alter table tblemp drop column phone;
  2. 按照下面要求分别写出修改表名的语句

    • 将表tbldept修改为dept
      alter table tbldept rename to dept;
    • 将表tblemp修改为emp
      alter table tblemp rename to emp;
  3. 创建一个临时表tmp1,包含id,name,表数据在事务提交时删除。
    create global temporary table tmp1(id number,name varchar2(20)) on commit delete rows;

  4. 创建一个临时表tmp2,包含id,name,表数据在事务提交时保留。
    create global temporary table tmp2(id number,name varchar2(20)) on commit preserve rows;

  5. 创建一个索引组织表student,包含sno,sname, sno为主键。
    create table student (sno number primary key,sname varchar2(20)) organization index;

  6. 创建一个分区表emp1,包含eid,ename,eage,egender, 按年龄做范围分区,第一个区年龄小于30,第二个分区年龄小于50,其他都放第三个分区。

    create table emp1(eid number,ename varchar2(20),eage number,egender varchar2(20)) 
    partition by range(eage)
    (
      partition p30 values less than(30),
      partition p50 values less than(50),
      partition pother values less than (maxvalue)
    );
    
  7. 创建一个分区表emp,包含eid,ename,eage,egender, 按年龄做范围间隔分区,25以下一个分区,其他的每5岁一个分区。

    create table emp2(eid number,ename varchar2(20),eage number,egender varchar2(20)) 
    partition by range(eage) interval (5)
    (
      partition p25 values less than(25)
    );
    
  8. 创建一个分区表emp3,包含eid,ename,eage,egender, 按性别做列表分区,“男”一个分区,“女”一个分区,其他的放一个分区。

    create table emp3(eid number,ename varchar2(20),eage number,egender varchar2(20)) 
    partition by list(egender)
    (
      partition pmale values ('男'),
      partition pfemale values ('女'),
      partition pother values (DEFAULT)
    );
    

实验五、表约束操作

写出下面表的建表语句
部门表 tbldept

字段 类型 说明
deptid number(5) 部门编号,主键
deptname varchar2(30) 部门名称,非空

员工表 tblemp

字段 类型 说明
empid number(5) 员工编号
empname varchar2(10) 员工名称
deptid number(5) 部门编号,外键,引用tbldept表的deptid
id varchar2(18) 身份证号,唯一
gender varchar2(10) 性别,只能是male或female

create table tbldept(deptid number(5) primary key,deptname varchar2(30)not null);
create table tblemp(empid number(5),empname varchar2(10),deptid number(5) references tbldept(deptid),id varchar2(18) unique,gender varchar2(10) check(gender='male' or gender='female'));

  1. 查询表tbldept和tblemp约束信息(user_constraints, user_cons_columns)
    select * from user_constraints where table_name in('TBLDEPT','TBLEMP');
    select * from user_cons_columns where table_name in('TBLDEPT','TBLEMP');

  2. 删除表tblemp外键约束。
    alter table tblemp drop constraint SYS_C005921;

  3. 修改表tbldept,增加部门所在房间号roomno,唯一
    alter table tbldept add roomno int unique;

  4. 修改表tblemp,在empid列上建立主键约束。
    alter table tblemp add primary key(empid);

  5. 修改表tblemp,在deptid列上建立外键约束,引用tbldept表的deptid列,并指定级联删除(on delete cascade)。
    alter table tblemp add foreign key(deptid) references tbldept(deptid) on delete cascade;

  6. 修改表tblemp,增加年龄列age,要求年龄介于20-40之间。
    alter table tblemp add age number(3) check(age>=20 and age<=40);

  7. 修改表tblemp,在empname列上增加非空约束。
    alter table tblemp modify empname not null;

实验六、视图、索引、序列等操作

员工表 emp

字段 类型 说明
no number(5) 编号,主键
name varchar2(30) 名称
gender varchar2(2) 性别
age number(2) 年龄
Salary number 工资

写出创建表语句。
drop table emp;
create table emp(no number(5) primary key,name varchar2(30),gender varchar2(6), age number(6),Salary number);

  1. 在emp表的no列 创建唯一索引idx1。
    create unique index idx1 on emp(no);

  2. 在emp表的gender列 创建位图索引idx2。
    create bitmap index idx2 on emp(gender);

  3. 创建一个序列emp_seq,起始值1,每次递增2,最大10000,循环;
    create sequence emp_seq start with 1 increment by 2 maxvalue 10000 cycle;
    drop sequence emp_seq;

  4. 修改序列emp_seq,缓存1000。
    alter sequence emp_seq CACHE 1000;

  5. 插入数据,使用序列生成员工号。

name gender age Salary
欧阳峰 21 5000
欧阳克 20 2500
洪七公 22 8000

insert into emp(no,name,gender,age,Salary) values(emp_seq.nextval,'欧阳峰','男',21,5000);
insert into emp(no,name,gender,age,Salary) values(emp_seq.nextval,'欧阳克','男',20,2500);
insert into emp(no,name,gender,age,Salary) values(emp_seq.nextval,'洪七公','男',22,8000);

  1. 创建视图v1,显示工资大于4500的员工信息,只读。
    drop view v1;
    create view v1 as select * from emp where salary>4500 with read only;

  2. 创建视图v2,通过该视图只能增删改工资小于3000的员工。
    drop view v2;
    create view v2 as select * from emp where salary>3000 with check option;

  3. 创建物化视图mv1,显示emp中工资大于5000的员工,当基本表数据变化时,只要提交物化视图更新数据。
    drop materialized view mv1;
    create materialized view mv1 refresh on commit as select * from emp where salary>5000;

  4. 创建物化视图mv2,显示emp中工资大于5000的员工,当基本表数据变化时,每隔5分钟刷新物化视图数据。
    drop materialized view mv2;
    create materialized view mv2 refresh start with sysdate next sysdate+5/1440 as select * from emp where salary>5000;

  5. 创建数据库链接link1,链接相邻同学的数据库,然后通过链接link1访问同学数据库中的表emp。
    drop database link link1;
    create database link link1 connect to u01 identified by u01 using 'mydb';

  6. 为通过数据库链接link1访问的emp表创建同义词 xxxx。
    drop synonym xxxx;
    create synonym xxxx for u01@link1;

实验七、数据操纵

按照下面表格信息写出创建表的语句

部门表 tbldept

字段 类型 说明
deptid number(5) 部门编号
deptname varchar2(30) 部门名称

员工表 tblemp

字段 类型 说明
empid number(5) 员工编号
empname varchar2(10) 员工名称
deptid number(5) 部门编号

create table tbldept(deptid number(5),deptname varchar2(30));
create table tblemp(empid number(5),empname varchar2(10),deptid number(5));
drop table tblemp;
drop table tbldept;

  1. 按照下面要求分别写出修改表结构的语句
    修改表tblemp,增加列phone,类型varchar2(20)
    alter table tblemp add phone varchar2(20);
    修改表tblemp,增加列age,类型number
    alter table tblemp add age number;
    修改表tblemp,增加列gender,类型varchar2(10)
    alter table tblemp add gender varchar2(10);
    修改表tblemp,将列empname类型修改为varchar2(20)
    alter table tblemp modify empname varchar2(20);
    修改表tblemp,删除列phone
    alter table tblemp drop column phone;

  2. 按照下面要求分别写出修改表名的语句
    将表tbldept修改为 dept
    alter table tblemp rename to emp;
    将表tblemp修改为 emp
    alter table tbldept rename to dept;

  3. 查看表dept和emp分别占用的了多少空间?(查看视图 user_extents,计算每个表占用的数据块数量,对blocks列求和)
    select * from user_extents where segment_name='DEPT';
    select * from user_extents where segment_name='EMP';

按照下面的数据写出插入语句

部门表 dept

deptid deptname
101 销售
102 研发
103 财务

员工表emp

empid empname deptid age gender
10101 张三 101 20
10102 李四 102
10103 王五 101 30
10201 赵六 30
10202 郑七 103 20
insert into dept values(101,'销售');
insert into dept values(102,'研发');
insert into dept values(103,'财务');

insert into emp values(10101,'张三',101,20,'男');
insert into emp values(10102,'李四',102,null,null);
nsert into emp values(10103,'王五',101,30,'女');
insert into emp values(10201,'赵六',null,30,'女');
insert into emp values(10202,'郑七',103,20,'男');
select * from dept;
select * from emp;

按下面要求写出操作语句

  1. 将性别为空的修改为 男(判断空 where gender is null)
    update emp set gender='男' where gender is null;
  2. 将 王五的 年龄修改为 32
    update emp set age=32 where empname='王五';
  3. 将 年龄为空的修改为25
    update emp set age=25 where age is null;
  4. 将 部门为空的修改为 103
    update emp set deptid=103 where deptid is null;
  5. 删除 所有女员工
    delete from emp where gender='女';
  6. 删除所有年龄大于25的员工
    delete from emp where age>25;
  7. 写出删除表dept和emp的语句
    drop table emp;
    drop table dept;

实验八、单表查询

create table emp(
  id number primary key,
  name varchar2(20),
  age number,
  gender varchar2(20),
  salary number,
  deptname varchar2(20)
);

insert into emp values(101,'李刚',30,'男',3000,'开发部');
insert into emp values(102,'王一帆',34,'男',4000,'销售部');
insert into emp values(103,'赵亮',28,'男',2600,'开发部');
insert into emp values(104,'王良',29,'男',2800,'开发部');
insert into emp values(105,'徐飞',32,'男',3600,'销售部');
insert into emp values(106,'钱永浩',30,'男',4000,'开发部');
insert into emp values(107,'李萍',40,'女',3600,'财务部');
insert into emp values(108,'曲刚',45,'男',4200,'财务部');
insert into emp values(109,'许文娟',31,'女',3000,'开发部');
insert into emp values(110,'赵宝乐',36,'男',3800,'销售部');
insert into emp values(111,'王望',38,'男',3200,'后勤部');
insert into emp values(112,'李三',40,'男',3400,'后勤部');
insert into emp values(113,'李大雷',33,'男',3200,'开发部');
insert into emp values(114,'王丽萍',37,'女',4700,'开发部');
insert into emp values(115,'郝云',31,'女',3500,'销售部');
insert into emp values(116,'赵轶平',42,'男',5000,'销售部');
insert into emp values(117,'王美华',24,'女',2500,'开发部');
insert into emp values(118,'李莉',39,'女',5200,'开发部');
commit;

  1. 查询所有员工信息,写出语句。
    select * from emp;

  2. 查询所有员工名称、部门名称和工资,写出语句。
    select name,deptname,salary from emp;

  3. 查询所有男员工的姓名和工资,写出语句。
    select name,salary from emp where gender='男';

  4. 查询所有年龄为空的男员工信息,写出语句。
    select * from emp where age is null;

  5. 查询所有姓张且工资大于5000的员工信息,写出语句。
    select * from emp where name like '张%' and salary>5000;

  6. 查询年龄在25和30之间的所有员工信息,写出语句。
    select * from emp where age between 25 and 30;

  7. 查询所有员工的平均工资、最大工资和最小工资,写出语句。
    select round(avg(salary),2),max(salary),min(salary) from emp;

  8. 查询各部门员工的平均工资、最大工资和最小工资,写出语句。
    select deptname,round(avg(salary),2),max(salary),min(salary) from emp group by deptname;

  9. 查询部门平均工资大于4500的部门名称和平均工资,写出语句。
    select deptname,round(avg(salary),2) from emp group by deptname having round(avg(salary),2)>3800;

  10. 查询员工的平均年龄,写出语句。
    select avg(age) from emp;

  11. 分页查询,每页5行,写出查询第二页的SQL语句。
    select * from emp offset 5 rows fetch next 5 rows only;

实验九、连接查询

create table tblclass(clano varchar2(5) primary key,claname varchar2(30));
insert into tblclass values('r1001','13软件1班');
insert into tblclass values('r1002','13软件2班');
commit;

create table tblcourse(couno varchar2(5)primary key,couname varchar2(30));
insert into tblcourse values('c01','操作系统');
insert into tblcourse values('c02','数据库');
insert into tblcourse values('c03','网络基础');
commit;

create table tblstudent(stuno varchar2(5) primary key,stuname varchar2(30),stuage number,clano varchar2(5) references tblclass(clano));
insert into tblstudent values('s1001','黎明',18,'r1001');
insert into tblstudent values('s1002','张晓刚',21,'r1001');
insert into tblstudent values('s1003','赵晓慧',20,'r1002');
commit;

create table tblscore(stuno varchar2(5) references tblstudent(stuno),couno varchar2(5) references tblcourse(couno),score number(5,2));
insert into tblscore values('s1001','c01',80);
insert into tblscore values('s1001','c02',75);
insert into tblscore values('s1001','c03',85);
insert into tblscore values('s1002','c01',90);
insert into tblscore values('s1002','c02',95);
insert into tblscore values('s1002','c03',95);
insert into tblscore values('s1003','c01',90);
insert into tblscore values('s1003','c02',85);
insert into tblscore values('s1003','c03',85);
commit;

create table tblemp(id number(5) primary key,name varchar2(20),mid number(5) references tblemp(id));
insert into tblemp values(1,'张亮',null);
insert into tblemp values(2,'李群',1);
insert into tblemp values(3,'王亦凡',1);
insert into tblemp values(4,'崔苗',2);
commit;

select * from tblclass;
select * from tblcourse;
select * from tblstudent;
select * from tblscore;
select * from tblemp;
  1. 查询学生学号、学生姓名及所在班级名称。
    select s.stuno,s.stuname,c.claname from tblstudent s,tblclass c where s.clano=c.clano;

  2. 查询学生名称、所在班级名称、课程名称及课程分数。
    select s.stuname,c.claname,cou.couname,sc.score from tblstudent s,tblclass c,tblcourse cou,tblscore sc where s.clano=c.clano and s.stuno=sc.stuno and sc.couno=cou.couno;

  3. 查询班级名称、课程名称及班级所有同学该门课程平均分数。
    select c.claname,cou.couname,avg(sc.score) from tblclass c,tblcourse cou,tblscore sc,tblstudent s where c.clano=s.clano and s.stuno=sc.stuno and sc.couno=cou.couno group by c.claname,cou.couname;

  4. 查询课程平均分数在80分以上的班级名称、课程名称及班级所有同学该门课程平均分数。
    select c.claname,cou.couname,avg(sc.score) from tblclass c,tblcourse cou,tblscore sc,tblstudent s where c.clano=s.clano and s.stuno=sc.stuno and sc.couno=cou.couno group by c.claname,cou.couname having avg(sc.score)>80;

  5. 查询班级名称、学生名称、学生课程的平均成绩。
    select c.claname,s.stuname,avg(sc.score) from tblclass c,tblstudent s,tblscore sc where c.clano=s.clano and s.stuno=sc.stuno group by c.claname,s.stuname;

  6. 查询平均分数在80以上的学生所属的班级名称、学生名称、学生平均成绩。
    select c.claname,s.stuname,avg(sc.score) from tblclass c,tblstudent s,tblscore sc where c.clano=s.clano and s.stuno=sc.stuno group by c.claname,s.stuname having avg(sc.score)>80;

  7. 查询课程名称、及该门课程的平均分、最高分、最低分。
    select cou.couname,avg(sc.score),max(sc.score),min(sc.score) from tblcourse cou,tblscore sc where cou.couno=sc.couno group by cou.couname;

  8. 查询(tblemp)员工编号、员工名称、员工主管编号、员工主管名称。
    select * from tblemp;
    select e1.id,e1.name,e2.id,e2.name from tblemp e1,tblemp e2 where e1.mid=e2.id;
    select e1.id,e1.name,e2.id,e2.name from tblemp e1 left join tblemp e2 on e1.mid=e2.id;

实验十、子查询

create table tblclass(clano varchar2(5) primary key,claname varchar2(30));
insert into tblclass values('r1001','13软件1班');
insert into tblclass values('r1002','13软件2班');
commit;

create table tblcourse(couno varchar2(5)primary key,couname varchar2(30));
insert into tblcourse values('c01','操作系统');
insert into tblcourse values('c02','数据库');
insert into tblcourse values('c03','网络基础');
commit;

create table tblstudent(stuno varchar2(5) primary key,stuname varchar2(30),stuage number,clano varchar2(5) references tblclass(clano));
insert into tblstudent values('s1001','黎明',18,'r1001');
insert into tblstudent values('s1002','张晓刚',21,'r1001');
insert into tblstudent values('s1003','赵晓慧',20,'r1002');
commit;

create table tblscore(stuno varchar2(5) references tblstudent(stuno),couno varchar2(5) references tblcourse(couno),score number(5,2));
insert into tblscore values('s1001','c01',80);
insert into tblscore values('s1001','c02',75);
insert into tblscore values('s1001','c03',85);
insert into tblscore values('s1002','c01',90);
insert into tblscore values('s1002','c02',95);
insert into tblscore values('s1002','c03',95);
insert into tblscore values('s1003','c01',90);
insert into tblscore values('s1003','c02',85);
insert into tblscore values('s1003','c03',85);
commit;

create table tblemp(id number(5) primary key,name varchar2(20),mid number(5) references tblemp(id));
insert into tblemp values(1,'张亮',null);
insert into tblemp values(2,'李群',1);
insert into tblemp values(3,'王亦凡',1);
insert into tblemp values(4,'崔苗',2);
commit;

select * from tblstudent;
select * from tblscore;
select * from tblcourse;
select * from tblclass;
select * from tblemp;

  1. 查询年龄最小的学生信息
    select * from tblstudent where stuage=(select min(stuage) from tblstudent);

  2. 查询每个班级年龄最小的学生信息
    select * from tblstudent e1 where stuage=(select min(stuage) from tblstudent where clano=e1.clano);

  3. 查询年龄小于所有学生平均年龄的学生信息。
    select * from tblstudent where stuage<(select avg(stuage) from tblstudent);

  4. 查询年龄小于所有不同班级平均年龄的学生信息。(使用 where age < all(子查询 ))
    select * from tblstudent where stuage

  5. 查询年龄大于任意不同班级平均年龄的学生信息。(使用 where age > any(子查询 ))
    select * from tblstudent where stuage>any(select avg(stuage) from tblstudent group by clano);

  6. 查询有两门以上课程成绩大于85分的学生名、班级名
    select s.stuname,c.claname from tblstudent s,tblclass c where s.clano=c.clano and s.stuno in( select stuno from tblscore where score>85 group by stuno having count(*)>2);

  7. 查询有两门以上课程成绩大于85分的学生名、班级名、课程和成绩
    select s.stuname,c.claname,cou.couname,sc.score from tblstudent s,tblclass c,tblcourse cou,tblscore sc where s.clano=c.clano and s.stuno=sc.stuno and sc.couno=cou.couno and sc.score>85 and s.stuno in( select stuno from tblscore where score>85 group by stuno having count(*)>2);

  8. 查询每名学生的平均成绩,要求输出学生名、平均成绩,并按成绩从大到小排序。
    select s.stuname,avg(sc.score) from tblstudent s,tblscore sc where s.stuno=sc.stuno group by s.stuname order by avg(sc.score) desc;

  9. 查询每门课程中得分最低的学生及课程信息,输出信息包括学生姓名、课程姓名和分数。
    select s.stuname,cou.couname,sc.score from tblstudent s,tblcourse cou,tblscore sc where s.stuno=sc.stuno and cou.couno=sc.couno and sc.score = (select min(score) from tblscore where couno=sc.couno);

  10. 查询所有不负责管理其他员工的员工信息。
    select * from tblemp e1 where not exists (select 1 from tblemp where mid=e1.id);

实验十一、函数

drop table student;
create table student(
	stuno number(5) primary key,
	stuname varchar2(30),
	gender varchar2(2),
	age number(2),
	birthday date
);
insert into student values(101,'张x三x ',null,null, to_date('1995-8-20', 'yyyy-mm-dd'));
insert into student values(201,' x李四x ','1',null, to_date('1996-7-1', 'yyyy-mm-dd'));
insert into student values(301,'王五六',2,null, to_date('1996-12-31', 'yyyy-mm-dd'));
commit;

select * from student;
  1. 查询生日是当月月末的学生信息。
    select * from student where birthday=last_day(birthday);

  2. 查询生日是当月月初的学生信息。
    select * from student where extract(day from birthday)=1;

  3. 查询生日是当月20日的学生信息。
    select * from student where extract(day from birthday)=20;

  4. 计算根据当前日期及学生生日计算每名学生年龄并更新学生表age列。
    select * from student;
    select stuname,ceil(months_between(sysdate,birthday)/12) from student;
    update student set age=ceil(months_between(sysdate,birthday)/12);

  5. 查询每名同学的下一个生日还有多少天。
    select stuname,add_months(birthday,age*12)-sysdate from student;

  6. 查询学生信息,年龄为空显示0,性别为1显示‘男’,2显示’女’,其他显示’未知’。
    select stuname,nvl(age,0),decode(gender,1,'男',2,'女','未知') from student;

  7. 去掉所有学生姓名中的’x’。
    update student set stuname=trim(replace(stuname,'x',''));
    commit;
    select * from student;

  8. 将学生姓名统一按照最长(字节长度)学生姓名从左补齐,补齐字符用’#’。
    rollback;
    update student set stuname= lpad(stuname,(select max(vsize(stuname)) from student),'#');
    select vsize(stuname) from student;

  9. 按照出生年份分组统计学生人数,输出信息包括出生年和人数。
    select extract(year from birthday),count(*) from student group by extract(year from birthday);

  10. 按照出生年份和月份分组统计学生人数,输出信息包括出生
    select extract(year from birthday),extract(month from birthday),count(*) from student group by extract(year from birthday),extract(month from birthday);
    select to_char(birthday,'yyyy-mm'),count(*) from student group by to_char(birthday,'yyyy-mm');

实验十二、PL/SQL基本语法

分别使用简单循环、FOR循环、while循环编写程序计算从1到100中能被7整除的整数个数。
set serveroutput on;

简单循环:

declare
s number:=0;
i number:=1;
begin
loop
exit when i>100;
if mod(i,7)=0 then
   s:=s+1;
end if;
i:=i+1;
end loop;
dbms_output.put_line(s);
end;

for循环:

declare
s number:=0;
begin
for i in 1..100 loop
if mod(i,7)=0 then
   s:=s+1;
end if;
end loop;
dbms_output.put_line(s);
end;

while循环:

declare
s number:=0;
i number:=1;
begin
while i<=100 loop
if mod(i,7)=0 then
   s:=s+1;
end if;
i:=i+1;
end loop;
dbms_output.put_line(s);
end;

分别使用简单循环、FOR循环、while循环编写实现5的阶乘。

简单循环:

declare
i number:=1;
r number:=1;
begin
loop
exit when i>5;
r:=r*i;
i:=i+1;
end loop;
dbms_output.put_line(r);
end;

for循环:

declare
a number:=1;
begin
for i in 1..5 loop
a:=i*a;
end loop;
dbms_output.put_line(a);
end;

while循环:

declare
s number:=1;
i number:=1;
begin 
while i<=5 loop
s:=s*i;
i:=i+1;
end loop;
dbms_output.put_line(s);
end;

编写程序,将给定字符串进行反向输出(例如: 输入’12345’,输出’54321’)。

declare
s varchar2(100):='12345';
t varchar2(100):='';
begin
for i in reverse 1..length(s) loop
   t:=t||substr(s,i,1);
end loop;
dbms_output.put_line(t);
end;

编写程序,输出以下图形

        *
      *   *
    *   *   *
      *   *
        *
declare
n number:=3;
begin
for i in 1..n loop
    dbms_output.put_line(lpad(' ',n-i,' ')||lpad('*',2*i-1,'*'));
end loop;
for i in reverse 1..n-1 loop
    dbms_output.put_line(lpad(' ',n-i,' ')||lpad('*',2*i-1,'*'));
end loop;
end;

实验十三、存储函数

编写一个函数func1,带一个整型输入参数n,计算参数n的阶乘并返回;

drop function func1;

create function func1(n number)
return number
is
r number:=1;
begin
for i in 1..n loop
r:=r*i;
end loop;
return r;
end;

select func1(5) from dual;

编写一个函数func2,带一个整型输入参数n,统计1到n之间奇数的个数并返回

drop function func2;

create function func2(n number)
return number
is
r number:=0;
begin
for i in 1..n loop
if mod(i,2)=1 then
r:=r+1;
end if;
end loop;
return r;
end;

select func2(100) from dual;

编写一个函数func3,带一个整型输入参数n,统计1到n之间奇数的和并返回

drop function func3;

create function func3(n number)
return number
is
r number:=0;
begin
for i in 1..n loop
if mod(i,2)=1 then
r:=r+i;
end if;
end loop;
return r;
end;

select func3(10) from dual;

编写一个函数func4,带一个CLOB类型输入参数source,统计输入参数中单词“hello”出现的次数并返回

drop function func4;

create or replace function func4(source clob,findstr varchar2)
return number
is 
slen number:=0;
tlen number:=0;
r number:=0;
begin
slen:=length(source);
tlen:=length(replace(source,findstr,''));
r:=(slen-tlen)/length(findstr);
return r;
end;

select func4('ahellobhelloc','hello') from dual;
select (length('axxbxxcxx')-length(replace('axxbxxcxx','xx','')))/length('xx') from dual;

编写一个过程proc1,带一个整型输入参数n,带一个输出型参数r,计算参数n的阶乘并返回;

drop procedure proc1;

create procedure proc1(n number,r out number)
is
begin
r:=1;
for i in 1..n loop
r:=r*i;
end loop;
end;

实验十四、触发器

  1. 假设存在:
    工人信息表:worker(工号wid,姓名wname,性别wgender,工资salary,所属部门dno,入职日期startdate);
    编写一个触发器worker_trig,当在表上执行insert时触发器被触发,插入工人数据时根据入职年份以及入职顺序自动生成员工编号wid。
    例:INSERT INTO worker VALUES(NULL,'李四','女',5000,101,'2022-04-01');
    工号8位,前4位为年份,后4位是顺序号从0001开始,如果入职年份是2022,则取2022年入职工人的最大工号加1
    create table worker(wid number,wname varchar2(20),wgender varchar2(20), salary number,dno number,startdate date);
drop trigger worker_trig;

create or replace trigger worker_trig
before insert
on worker
for each  row
declare
w_maxid number;
w_year varchar(20);
begin
w_year:=to_char(:new.startdate,'yyyy');
select nvl(max(wid),to_number(w_year)*10000)+1 into w_maxid from worker where to_char(startdate,'yyyy')='w_year';
:new.wid:=w_maxid;
end;

INSERT INTO worker VALUES(NULL,'李四','女',5000,101,to_date('2021-04-01','yyyy-mm-dd'));
INSERT INTO worker VALUES(NULL,'李四','女',5000,101,to_date('2022-04-01','yyyy-mm-dd'));
select * from worker;

drop table worker;
  1. 假设存在:
    工人信息表:worker(工号wid,姓名wname,性别wgender,工资salary,所属部门dno,入职日期startdate);
    编写一个触发器worker_trig,当在表上执行insert时触发器被触发,插入工人数据时根据性别以及入职顺序自动生成工号wid。
    例:INSERT INTO worker VALUES(NULL,'李四','女',5000,101,'2022-04-01');
    工号5位,第1位为性别标识(1代表男性,2代表女性),后4位是顺序号从0001开始,如果入职的是男性员工,则取男性员工的最大编号加1,否则取女性员工的最大编号加1
drop trigger worker_trig;
delete * from worker;

create or replace trigger worker_trig
before insert
on worker
for each row
declare
w_maxid number;
begin 
if :new.wgender='男' then
select nvl(max(wid),10000)+1 into w_maxid from worker where wgender='男';
else
select nvl(max(wid),20000)+1 into w_maxid from worker where wgender='女';
end if;
:new.wid:=w_maxid;
end;

INSERT INTO worker VALUES(NULL,'李四','女',5000,101,to_date('2021-04-01','yyyy-mm-dd'));
INSERT INTO worker VALUES(NULL,'李四','女',5000,101,to_date('2022-04-01','yyyy-mm-dd'));
INSERT INTO worker VALUES(NULL,'李四','男',5000,101,to_date('2022-04-01','yyyy-mm-dd'));
select * from worker;
  1. 假设存在:
    产品生产表:product(生产年份year,生产月份month,商品名称pname,生产数量quantity);
    统计表:stats(生产年份year,商品名称pname,累计生产数量total);
    编写一个触发器product_trig,当在表product上执行insert时触发器被触发,将生产数量累加到表stats的相应年份相应商品的累计生产数量上。
    例:INSERT INTO product VALUES(2020,9,'面包',1000);
    将生产数量500累加到统计表stats的相应年份2021年相应商品“面包”的累计生产数量上。
drop table product;
drop table stats;
drop trigger product_trig;

create table product(year number,month number,pname varchar2(100),quantity number);
create table stats(year number,pname varchar2(100),total number);

create or replace trigger product_trig
after insert
on product
for each row
declare
flag number:=0;
begin 
select count(*) into flag from stats where year=:new.year and pname=:new.pname;
if flag=0 then
insert into stats values(:new.year,:new.pname,:new.quantity);
else
update stats set total=total+:new.quantity where year=:new.year and pname=:new.pname;
end if;
end;

INSERT INTO product VALUES(2020,9,'面包',1000);
select * from stats;

你可能感兴趣的:(Oracle,数据库,oracle)