江科大数据库实验

本实验采用SQLite数据库完成。
由于sqlite不完全支持sql标准,因此我采用python3来模拟一部分函数定义和存储过程。

准备过程

单击这里下载sqlite3的压缩包,然后解压到桌面。
像这样。

然后使用win+R 运行cmd shell

数据定义

cd 到桌面,然后运行(按要求学号后三位+db即可)代码如下:

sqlite3 108.db

运行结果如下

教师表(JS)

复制下面的代码然后粘贴到cmd中

create table JS(
    Tno varchar(7),
    Tname varchar(10),
    Tsex varchar(2),
    Birthday datatime,
    Dept varchar(20),
    Sid varchar(18)
);

插入

INSERT INTO JS VALUES('T001','刘威','女','1971-3-20','电信','551021197103203121');
INSERT INTO JS VALUES('T002','张琪劲','男','1963-7-13','数理','32010119630713318X');
INSERT INTO JS VALUES('T003','李子文','女','1973-9-15','电信','551021197103203121');
INSERT INTO JS VALUES('T004','江海防','女','1960-2-18','社科','560102196002185623');
INSERT INTO JS VALUES('T005','李铁','男','1977-10-11','数理','230103197710118632');
INSERT INTO JS VALUES('T006','吴天一','男','1962-4-23','电信','320104196204237516');
INSERT INTO JS VALUES('T007','赵志华','男','1968-8-27','社科','321102196808277214');
INSERT INTO JS VALUES('T008','钱进','男','1980-7-10','电信','570102198007103452');
INSERT INTO JS VALUES('T009','孙星南','女','1981-3-2','外语','110102198103024125');
select * from JS;

课程表(Course)

复制下面的代码然后粘贴到cmd中

create table Course(
    Cno varchar(10),
    Cname varchar(20),
    Credit integer,
    property varchar(10),
    Hours integer
);

插入数据:

INSERT INTO Course VALUES('01010101','大学英语1',4,'考试','');
INSERT INTO Course VALUES('01010102','普通物理1',4,'考试','');
INSERT INTO Course VALUES('01010103','高等数学1',6,'考试','');
INSERT INTO Course VALUES('01010104','形势政策',2,'考查','');
INSERT INTO Course VALUES('01010105','计算机基础',4,'考查','');

授课表

create table SK(
    Tno varchar(7),
    Cno varchar(10),
    Hours integer
);

插入数据:

INSERT INTO SK VALUES('T001','01010105',64);
INSERT INTO SK VALUES('T002','01010102',64);
INSERT INTO SK VALUES('T009','01010101',64);
INSERT INTO SK VALUES('T004','01010104',32);
INSERT INTO SK VALUES('T005','01010103',96);
INSERT INTO SK VALUES('T006','01010105',64);
INSERT INTO SK VALUES('T003','01010101',64);
select * from SK;

修改表结构

1)在授课表中添加一个授课类别,列名为Type,类型为char(4)

ALTER TABLE SK ADD COLUMN Type char(4);

查看更改结果

select * from sqlite_master where type = "table";


更改完毕

2)将授课表中的Hours的类型改为Smallint

因为Sqllite不能修改字段或者删除字段,这里我直接删表重建。如果是mysql就使用alter table news modify column Hours smallint;

drop table SK;
create table SK(
    Tno varchar(7),
    Cno varchar(10),
    Hours Smallint
);
INSERT INTO SK VALUES('T001','01010105',64);
INSERT INTO SK VALUES('T002','01010102',64);
INSERT INTO SK VALUES('T009','01010101',64);
INSERT INTO SK VALUES('T004','01010104',32);
INSERT INTO SK VALUES('T005','01010103',96);
INSERT INTO SK VALUES('T006','01010105',64);
INSERT INTO SK VALUES('T003','01010101',64);
select * from SK;

3)删除课程表的Hours列

和上面一个道理

drop table SK;
create table SK(
    Tno varchar(7),
    Cno varchar(10)
);
INSERT INTO SK VALUES('T001','01010105');
INSERT INTO SK VALUES('T002','01010102');
INSERT INTO SK VALUES('T009','01010101');
INSERT INTO SK VALUES('T004','01010104');
INSERT INTO SK VALUES('T005','01010103');
INSERT INTO SK VALUES('T006','01010105');
INSERT INTO SK VALUES('T003','01010101');
select * from SK;

完成以下功能:

1) 定义表students

其中字段有:SNO CHAR(10) 、 SNAME CHAR(8) 、 AGE NUMERIC(3,0)、 SEX CHAR(2)、 BPLACE CHAR(20)、Polity CHAR(20)。要求SNO和SNAME不为空,SNO为主键。

create table students(
    SNO CHAR(10) PRIMARY KEY NOT NULL,
    SNAME CHAR(8) NOT NULL,
    AGE NUMERIC(3,0),
    SEX CHAR(2),
    BPLACE CHAR(20),
    Polity CHAR(20)
);

2) 在教师表JS中增加住址列

字段名为ADDR,类型为 CHAR,长度50。

ALTER TABLE JS ADD COLUMN TDDR char(50);

3) 根据students表

建立一个只包含学号、姓名、年龄的女学生表,表名为GRIL。

create table GRIL(
    SNO CHAR(10) PRIMARY KEY NOT NULL,
    SNAME CHAR(8) NOT NULL,
    AGE NUMERIC(3,0)
);

4) 建立一成绩表

表名为score,其中字段有:SNO CHAR(10),CNO CHAR(10),scoreNUMERIC(6,0),并输入部分记录,内容自定

create table score(
    SNO CHAR(10),
    CNO CHAR(10),
    score NUMERIC(6,0)
);

insert into students values('8101','张三','','','','');
insert into students values('8102','李四','','','','');
insert into score values('8101','01010101',60);

定义索引

在数据库中的新建一个数据表

名为js1,结构与js表相同。为js1表创建一个唯一聚集索引,索引字段为Sid,索引名为I_js_sid。

create table JS1(
    Tno varchar(7),
    Tname varchar(10),
    Tsex varchar(2),
    Birthday datatime,
    Dept varchar(20),
    Sid varchar(18)
);
create INDEX I_js_sid ON JS1 (Sid);
SELECT * FROM sqlite_master WHERE type = 'index';

为数据库中的course数据表

创建一个复合索引,索引名为I_cource_xf,使用Cno和Credit字段

CREATE INDEX I_cource_xf on Course(Cno, Credit);
SELECT * FROM sqlite_master WHERE type = 'index';

完成后输入.exit退出

思考与实践

1.创建“图书借阅数据库”。
2.修改“图书借阅数据库”,相关参数自行确定。
3.在“图书借阅数据库”中创建以下四个表,并分别为这四个表写入部分数据,内容自定(提醒:各表数据之间的相关性)

创建个数据库

sqlite3 图书借阅.db

cmd中运行如下sql语句

create table JS(
    Jsno varchar(6),
    Jname varchar(10),
    Jdw varchar(20)
);
create table TS(
    Tsno varchar(15),
    Tname varchar(20),
    Tnum smallint,
    Tpos varchar(30),
    Cno varchar(4)
);
create table CBS(
    Cno varchar(4),
    Cname varchar(20),
    Ctel varchar(12),
    Cyb varchar(6),
    Caddr varchar(40)
);
create table JY(
    Jsno varchar(6),
    Tsno varchar(15),
    Jydate datetime,
    Hdate datetime
);
.table

运行效果如下

插入数据

insert into JS values('000000','张三','江科大');
insert into JS values('000001','李四','江科大');
insert into JS values('000002','王五','江科大');
insert into TS values('0000000001','第一本书',10,'江苏镇江','0001');
insert into TS values('0000000002','第二本书',10,'江苏镇江','0001');
insert into TS values('0000000003','第三本书',10,'江苏镇江','0001');
insert into TS values('0000000004','第四本书',10,'江苏镇江','0001');
insert into CBS values('0001','江科大出版社','12345678910','111111','江科大');
insert into JY values('000000','0000000001','2019-11-18','2019-11-18');

创建视图

TS_view
CREATE VIEW TS_view AS select Tsno,Tname,Cname,Tnum from TS,CBS where TS.Cno=CBS.Cno;
select * from TS_view;

Jy_view
CREATE VIEW Jy_view AS
select JS.Jsno,Jname,TS.Tname,TS.Cno,Jydate,Cname,Hdate from JS,TS,CBS,JY where JS.Jsno = JY.Jsno and TS.Tsno=JY.Tsno;
select * from Jy_view;

建立索引

随便建建

create INDEX ts_index ON TS(Tsno);
create INDEX jy_index ON JY(Jsno);
create INDEX cbs_index ON CBS(Cno);
create INDEX js_index ON JS(Jsno);

完整性约束

删表重建吧。
懒得写了。草


数据操纵

1. 在查询分析器中,对“教师授课管理数据库”表中数据进行下列查询操作

(1)查询所有男学生的姓名、出生日期。

 select SNAME,BPLACE from students where SEX='男';

运行效果如下:

(2)查询男女教师的人数。

select Tsex,count(Tno) from JS group by Tsex;

运行效果如下:

(3)找出年龄在20~23岁之间的学生的学号、姓名和年龄,并按年龄升序排序。

select * from students where AGE>=20 and AGE<=23;

懒得填数据了,把20改成18就能查出来了

(4)找出年龄超过平均年龄的学生姓名。

select SNAME from students where AGE>(select avg(AGE) from students);

(5)查询成绩不及格的学生信息,包括姓名、学号、课程名和成绩。

select SNAME,Students.SNO,Course.Cname,score.score
from students,Course,score
where score.score<60 and students.SNO=score.sno and score.Cno=Course.Cno;

(6)查询所有讲授“01010105”课程的教师信息。

SELECT JS.Tno,Tname,Tsex,Birthday,Dept,Sid from JS,SK where JS.Tno=SK.Tno and SK.Cno='01010105';

(7)查询1971年以前(含1971年)出生的所有教师的任课信息,包括教师姓名、出生日期、所授课程名、学时数。

select Tname,Birthday,Course.Cname,Course.Hours 
from JS,Course,SK 
where JS.Birthday<'1972-1-1' and JS.Tno=SK.Tno and Course.Cno=SK.Cno;

(8)查询所有未授课的教师信息。

select * from JS where JS.Tno not in (select JS.Tno from JS,SK where JS.Tno = SK.Tno);

2.在查询分析器中,对表中数据进行插入操作

(1)向students表中插入几条记录,内容自定。

insert into students values('8089','张八','女','','','');

(2)把教师李映雪(教师号为1476,其他内容自定)的记录加入到教师表JS中。

insert into JS values('T010','李映雪','女','1971-3-20','电信','551021197103203181','');

(3)根据students表,建立一个只包含学号、姓名、年龄的女学生表,表名为GRIL。

建过了

3.在查询分析器中,对表中数据进行修改操作

(1)把所有学生的年龄增加一岁。

update students set AGE=AGE+1;

(2)将所有选修某一指定课程的学生成绩增加5分。

update score set score=score+5 where Cno='01010101';

(3)将某个学生的所有成绩置0。

update score set score = 0 where Sno='8102';

4.在查询分析器中,对表中数据进行删除操作

(1)从教师表JS中删除年龄已到60岁的退休教师的数据。

drop from JS where datetime(CURRENT_TIMESTAMP,'localtime')-Birthday>59;

(2)将学生表student中的某个学生删除,并删除其他表中与该学生相关的信息。

一个一个删吧。如果用外键的话,直接

drop from student where SNO=?

FOREIGN KEY 学生信息ID
REFERENCES 学生信息 (学生信息ID)
ON DELETE CASCADE


数据库编程

T-SQL的流程控制语句、游标的使用编写程序完成以下功能,在查询分析器中执行程序,并记录结果。

T-SQL的流程控制语句、游标的使用

1.

在score表中求某班学生某门课程的最高分和最低分的学生信息,包括学号、姓名、课程名、成绩四个字段。

正常查询如下所示:

最高分:

SELECT students.SNO,students.SNAME,Course.Cname,score 
FROM score,students,Course
where students.SNO=score.SNO and Course.Cno=score.Cno 
ORDER BY score DESC 
limit 1;

查询结果如下

最低分:

SELECT students.SNO,students.SNAME,Course.Cname,score 
FROM score,students,Course 
where students.SNO=score.SNO and Course.Cno=score.Cno 
ORDER BY score ASC limit 1;

查询结果如下

2.

查询某班的学生信息,要求列出的字段为:班级、本班内的学号、姓名、性别、出生日期、政治面貌

增加一个班级表 banji 和一个班级学生关系表:

create table banji(
    Bno varchar(4),
    Bname varchar(20)
);
create table banji_student(
    Sno char(10),
    Bno varchar(4)
);

向表内添加数据:

insert into students values('8103','张五',18,'男','1999-08-07','团员');
insert into students values('8104','李五',18,'女','1998-09-04','党员');
insert into banji values('100','一班');
insert into banji_student values('8103','100');
insert into banji_student values('8104','100');

查询一班的学生信息:

select banji.Bname, students.SNO,students.SNAME,students.SEX,students.BPLACE,students.Polity
from  banji,banji_student,students
where banji.Bno = 100 and banji_student.Sno = students.SNO

3.

在student表中先插入三条新记录,其中的Pollity字段的值为NULL,要求对记录进行查询时,对应的NULL值在显示时显示为“群众”

drop table students;
create table students(
    SNO CHAR(10) PRIMARY KEY NOT NULL,
    SNAME CHAR(8) NOT NULL,
    AGE NUMERIC(3,0),
    SEX CHAR(2),
    BPLACE CHAR(20),
    Polity CHAR(20) DEFAULT '群众'
);
insert into students values('8103','张五',18,'男','1999-08-07','团员');
insert into students values('8104','李五',18,'女','1998-09-04','党员');
insert into students values('8101','张三','','','','');
insert into students values('8102','李四','','','','');
select * from students;
insert into students(SNO,SNAME,AGE,SEX,BPLACE) values('8105','王八',18,'男','1999-08-08');

4.

根据score表中考试成绩,查询某班学生某门课程的平均成绩,并根据平均成绩输出相应的提示信息
向score表中添加数据

insert into score values('8102','01010101',50);
SELECT avg(score),Course.Cname,banji.Bname
FROM score,students,Course,banji,banji_student
where Course.Cno=score.CNO and banji.Bno=banji_student.Bno 
and banji.Bno=100 and banji_student.Sno = students.SNO and banji_student.Sno=score.SNO;

5.

根据score表中考试成绩,查询某班学生的考试情况,并使用CASE将课程号替换为课程名称

SELECT score,(case score.CNO when 1 then Course.Cname ELSE Course.Cname END),banji.Bname
FROM score,students,Course,banji,banji_student
where Course.Cno=score.CNO and banji.Bno=banji_student.Bno 
and banji.Bno=100 and banji_student.Sno = students.SNO and banji_student.Sno=score.SNO;

6.

根据score表中考试成绩,查询某班学生的考试情况,并根据考试分数输出考试等级。

SELECT students.SNAME,(case when score >=60 then '及格' else '不及格' end),Course.Cname,banji.Bname
FROM score,students,Course,banji,banji_student
where Course.Cno=score.CNO and banji.Bno=banji_student.Bno 
and banji.Bno=100 and banji_student.Sno = students.SNO and banji_student.Sno=score.SNO;

存储过程的创建与调用

因为sqlite功能有限。这里选择python来模拟逻辑。

1.

创建一个存储过程stuscoreinfo,完成的功能是在表student、表course和表score中查询以下字段:班级、学号、姓名、性别、课程名称、考试分数。

先修改一下张三的性别

update students set SEX='女' where SNAME='张三';

编写sql语句

select banji.Bname,students.SNAME,students.SEX,Course.Cname,score.score
from banji,banji_student,students,Course,score
where banji.Bno=banji_student.Bno and banji_student.Sno=students.SNO and score.Cno=Course.Cno and score.Sno=students.SNO;

使用python进行封装调用。
python 代码如下:

import sqlite3
def stuscoreinfo():
	conn = sqlite3.connect('108.db')
	cursor = conn.cursor()
	cursor.execute("select banji.Bname,students.SNAME,students.SEX,Course.Cname,score.score from banji,banji_student,students,Course,score where banji.Bno=banji_student.Bno and banji_student.Sno=students.SNO and score.Cno=Course.Cno and score.Sno=students.SNO;")
	values = cursor.fetchall()
	print (values)
	cursor.close()
	conn.close()
stuscoreinfo()

运行结果如下所示

2.

创建一个带有参数的存储过程stu_info,该存储过程根据传入的学生编号,在student中查询此学生的信息。

编写sql如下所示

select * from students where SNO='8101'

python封装如下

import sqlite3
def stu_info(num):
	conn = sqlite3.connect('108.db')
	cursor = conn.cursor()
	cursor.execute("select * from students where SNO='"+str(num)+"'")
	values = cursor.fetchall()
	print (values)
	cursor.close()
	#conn.commit()
	conn.close()
stu_info(8101)

运行结果如下

3.

创建一个带有参数的存储过程stu_age,该存储过程根据传入的学生编号,在student中计算此学生的年龄,并根据程序执行结果返回不同的值,程序执行成功,返回整数0,如果执行错误,则返回错误号。

import sqlite3
import time
def stu_age():
	try:
		conn = sqlite3.connect('108.db')
		cursor = conn.cursor()
		cursor.execute("select BPLACE,SNAME from students");
		values = cursor.fetchall()
		for i in values:
			if i[0].split('-')[0]!='':
				print (str(int(time.localtime(time.time())[0])-int(i[0].split('-')[0]))+'|'+str(i[1]))
			else:
				print ('未填写' + '|'+str(i[1]))
		cursor.close()
		conn.close()
		return 0
	except BaseException:
		return 1
stu_age()

运行结果如下:

4-8

上面均已经python模拟了存储过程的逻辑。

自定义函数的创建与调用

1.

使用自定义函数fun_sumscores。求score表中各班级的各门课程的平均分。主程序调用该函数,显示各班级、各课程的平均分。

这是修改sql之前的信息
编写sql语句如下:

select banji.Bname,avg(score),Course.Cname
from banji,score,banji_student,Course
where banji.Bno=banji_student.Bno and banji_student.Sno=score.Sno and Course.Cno=score.Cno
group by Course.Cname;

python封装如下

import sqlite3
def fun_sumscores():
	try:
		conn = sqlite3.connect('108.db')
		cursor = conn.cursor()
		cursor.execute("select banji.Bname,avg(score),Course.Cname from banji,score,banji_student,Course where banji.Bno=banji_student.Bno and banji_student.Sno=score.Sno and Course.Cno=score.Cno group by Course.Cname;");
		values = cursor.fetchall()
		print (values)
		cursor.close()
		conn.close()
		return 0
	except BaseException:
		return 1
fun_sumscores()

运行效果如下:

2.

编写一个用户自定义函数fun_sumscores。要求根据输入的班级号和课程号,求得此班此门课程的总分。主程序调用该函数,查询指定班级的某课程的总分。
编写sql如下

select Cname,sum(score)
from score,banji,banji_student,Course
where banji.Bno=100 and score.Cno='01010101' and Course.Cno=score.Cno and banji.Bno=banji_student.Bno and banji_student.Sno=score.SNO;

python封装如下

import sqlite3
def fun_sumscores(Bno,Cno):
	try:
		conn = sqlite3.connect('108.db')
		cursor = conn.cursor()
		cursor.execute("select Cname,sum(score) from score,banji,banji_student,Course where banji.Bno="+Bno+" and score.Cno='"+Cno+"' and Course.Cno=score.Cno and banji.Bno=banji_student.Bno and banji_student.Sno=score.SNO;");
		values = cursor.fetchall()
		print (values)
		cursor.close()
		conn.close()
		return 0
	except BaseException:
		return 1
fun_sumscores('100','01010101')

运行效果如下

3.

编写一自定义函数,用于查询给定姓名的学生,如果没找到,返回0,否则返回满足条件的学生人数。主程序调用该函数,查询“李浩”的学生,并根据函数的返回值进行输出。

编写sql如下

select count(*) from students where SNAME='张三';

python模拟如下

import sqlite3
def fun_select(name):
	try:
		conn = sqlite3.connect('108.db')
		cursor = conn.cursor()
		cursor.execute("select count(*) from students where SNAME='"+name+"'")
		values = cursor.fetchall()
		print (values)
		cursor.close()
		conn.close()
		return 0
	except BaseException:
		return 1
fun_select('张三')

运行效果如下:

思考与实践

对“图书借阅数据库”中的JS、TS、CBS、JY表进行操作:
查询各借书人的借阅量(若重复借阅一本书,则以一本书计),要求得到:借书证号、姓名、借书量。

编写sql

select JS.Jsno,JS.Jname,count(JY.Jsno)
from JS,JY
where JS.Jsno=JY.Jsno
Group by JS.Jsno;

运行效果如下

posted @ 2019-11-18 16:16  秃桔子  阅读(2862)  评论(5编辑  收藏  举报

如果您有编程方面或者学术方面的需求请在微信公众号搜索

桔子科研


或者识别下方二维码,第一时间获取编程有趣的知识和最新科研学术成果。