spacer.gif




数据库课程设计报告












设计题目         学生选课系统

spacer.gifspacer.gif专    业         计算机科学与技术

班    级         1101

spacer.gifspacer.gif学    号      

姓    名        寸利芳

spacer.gifspacer.gif完成日期      2014



目  录


1 设计任务和要求3

2 需求分析3

2.1 功能需求3

2.2 性能需求3

2.3 数据需求3

2.4 运行需求3

3 系统设计4

3.1 总体功能框架设计4

3.2 模块的详细设计4

3.3 功能分配4

3.4 处理流程5

3.5 主要功能的原理及实现算法5

4 数据库设计10

4.1 概念结构设计10

4.2 逻辑结构设计12

4.3 物理结构设计12

5 运行结果与测试13

5.1 运行界面极其效果图13

5.2 问题说明18

6 课程设计总结与体会19

   6.1 系统实现的技术方案评价19

   6.2 软件质量评价20

6.3 课程设计过程中软件开发时间分配评价20

6.4 经验与教训20

6.5 总结与体会20

7参考资料20

















1.设计任务与要求

1.1任务

    结合数据库与vc++编程技术开发出符合要求的学生选课系统软件,以实现学生选课的基本功能。

 1.2 任务分配:李丹设计实现数据库

孙亭负责实验报告,E-R图

张晔、寸利芳负责整个系统的功能实现:代码的编写及界面的设计  

 1.3要求

掌握使用现行较流行的数据库管理系统或数据库开发工具进行数据库管理操作(如建库、建立完整性约束,对数据库中数据进行查询,更改等操作)的方法;同时,会使用一种开发工具开发出有相当完善功能并有一定规模的数据库应用系统。通过练习对SQL语言要有较深入的了解和掌握,对数据库的管理(主要是安全性、完整性方面)要有一定程度的了解,对表、视图(存储过程、触发器这两个可选)等的应用达到熟练水平.

2.需求分析

 2.1 功能需求

     2.1.1学生用户学生通过输入学号和密码进下该系统后,可以查询可选课程信息,查看选课情况结果,并且依据自己的需求选课或者退课。

2.1.2系统管理员用户在此系统中,学校工作人员在输入工号和密码的情况下进入系统,可以为添加学生信息让新入学的同学也可以选课,还有录入成绩的功能,查询选课功能在这个功能中每门课都显示有已报人数与限报人数,防止某些课报的人太多影响上课,还有增加课程信息和删除课程信息的功能。

2.2 性能需求

 2.2.1 时间特性要求:在软件方面,响应时间,更新处理时间都要求比较快而且迅速,这就需要采用存储过程技术,才能够满足用户的需要,如终止选课事物,当学生选课多于5门并且每门课的选课人数超出所限定人数时,提示选课不成功界面

 2.2.2 安全性:设立口令号和密码验证方式,防止非法用户登录进行操作。也就是用户只有学生和管理员才能进入这个系统。

 2.3 数据需求

    2.3.1基本表

学生信息:学号,姓名,班级,已选课数

课程信息:课程号,课程名,教师名,上课地点,课程时间,课程学分,已报人数,限报人数

选课信息:编号,学号,课程名,学分,成绩

登录信息:学号,密码

平均成绩:编号,课程号,平均成绩

2.3.2数据之间有级联删除关系:即,当一个学生退学时,需先删除该学生的选课信息,才能删除该学生的基本信息。

2.4 运行需求

2.4.1 登陆界面必须有学生和管理员两种登陆方式,各自凭借各自的口令与密码进入。

2.4.2  SqlServer与vc++结合。

3.系统设计

3.1总体功spacer.gifspacer.gifspacer.gif能框架设计

spacer.gif


spacer.gifspacer.gif

spacer.gifspacer.gif


spacer.gifspacer.gif


spacer.gifspacer.gif

spacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gif

spacer.gif


spacer.gif

spacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gif








系统功能图


3.2模块的详细设计

(1) 学生的属性:学号、姓名、班级已选课数

(2) 密码的属性:学号、密码、标记

(3) 选课的属性:编号、学号、课程名、课程号、学分、成绩

(4) 课程的属性:课程号课程名、教师名、上课地点、课程时间、课程学分、已报人数、限报人数

(5) 平均成绩属性:编号、课程号、平均成绩

 注:平均成绩的主属性为编号,该属性自动增加,独一无二

3.3功能分配

3.3.1管理员功能

u 登录:通过输入管理员账号和密码进入管理界面。

u 增加学生:输入学生姓名、学号、班级、密码实现增加学生功能。

u 输入成绩:输入课程号,从学号下拉菜单中选择应选择的学生,该学生的姓名、班 级则自动补全,输入学生的成绩,确定即可。

u 查询选课情况:输入所查询课程的课程号,点击查询按钮,即可看到该课程所对应的课程名、已报人数、限报人数、学分。

u 编辑课程:

       增加课程:输入课程号、课程名、任课老师、上课地点、上课时间、学分,点击增加即可。

删除课程:输入课程号,点击删除即可。

   3.3.2学生功能

u 登录:通过输入学生口令和密码进入学生操作界面。

u 选课:输入课程号,点击确定即可成功。

u 编辑已选课程:进入此页面后,即可查看所选的课程,也可删除已选的课程。

u 查询成绩:进入此页面后,选择时间段即可查询。

u 修改查询密码:按照提示,输入一次旧密码,输入两次新密码,确定即更改成功。        

 3.4处理流程

spacer.gif     3.4.1管理员处理流程

spacer.gifspacer.gif

    3.4.2学生处理流程

spacer.gifspacer.gifspacer.gifspacer.gifspacer.gif

 3.5主要功能的原理及实现算法:

     1.选课代码:

void CSelect::OnEnter()  

{UpdateData(TRUE);

if(m_coursecode=="")

{

MessageBox("请输入你要选的课程号");

return;

}

   CDatabase db1;

db1.Open(_T("socc"),FALSE,FALSE,_T("ODBC;"),FALSE);

CString temp2,temp3,temp4,temp5,temp6,temp7,temp8,temp9,temp10,temp11,temp12,temp13,coursename;

temp2.Format("select * from password where flag=%d",1);

CRecordset rs1(&db1);

rs1.Open(AFX_DB_USE_DEFAULT_TYPE,temp2);

rs1.GetFieldValue("学号",temp3);  

   temp10.Format("select * from student where 学号=%s",temp3);

CRecordset rs5(&db1);

rs5.Open(AFX_DB_USE_DEFAULT_TYPE,temp10);

rs5.GetFieldValue("已选课数",temp9);  

if(5==atoi(temp9))

{MessageBox("你的选课已满五门,不能再选!");

return;

}

temp12.Format("select * from course where 课程号=%s",m_coursecode);

CRecordset rs6(&db1);

rs6.Open(AFX_DB_USE_DEFAULT_TYPE,temp12);

rs6.GetFieldValue("已报人数",temp13);  

if(30==atoi(temp13))

{MessageBox("此课程已报满,请选其它的课程!");

return;

}

   UpdateData(TRUE);

temp10.Format("select * from StudentCourse where 学号=%s",temp3);

   CRecordset rs4(&db1);

rs4.Open(AFX_DB_USE_DEFAULT_TYPE,temp10);

if(!rs4.IsEOF())

{

rs4.MoveFirst();

while(!rs4.IsEOF())

{

           rs4.GetFieldValue("课程号",temp9);

if(temp9==m_coursecode)

{

MessageBox("此课程已选");

return;

}

rs4.MoveNext();

       }

       }

temp4.Format("select * from course where 课程号=%s",m_coursecode);

CRecordset rs2(&db1);

rs2.Open(AFX_DB_USE_DEFAULT_TYPE,temp4);

   if(rs2.IsEOF())

 {MessageBox("无此课程,请查清后再输!!!");return;

 }

   rs2.GetFieldValue("课程名",coursename);

rs2.GetFieldValue("课程学分",temp11);

temp5.Format("Insert into StudentCourse (学号,课程名,课程号,学分,成绩)values('%s','%s','%s','%s','0')",temp3,coursename,m_coursecode,temp11);

db1.ExecuteSQL(temp5);

temp6.Format("update student set 已选课数=已选课数+1 where 学号=%s",temp3);

db1.ExecuteSQL(temp6);

   temp7.Format("update course set 已报人数=已报人数+1 where 课程号=%s",m_coursecode);

   db1.ExecuteSQL(temp7);

   MessageBox("选课成功");

db1.Close();

}

2.增加学生代码:

void CAddStudent::OnEnsure()

{

UpdateData(TRUE);

CString temp,temp2;

if(m_name=="" || m_classnum=="" || m_password=="" || m_class=="")

{

MessageBox("请输入完整的信息!!!");

return;

}

temp2.Format("select * from student where 学号=%s",m_classnum);

CDatabase db;

db.Open(_T("socc"),FALSE,FALSE,_T("ODBC;"),FALSE);

CRecordset rs(&db);

rs.Open(AFX_DB_USE_DEFAULT_TYPE,temp2);

if(!rs.IsEOF())

{

MessageBox("该学号已有,请重新输入!");

return;

}

temp.Format("Insert into password (学号,密码)values('%s','%s')",m_classnum,m_password);

db.ExecuteSQL(temp);

temp.Format("Insert into student (姓名,学号,班级)values('%s','%s','%s')",m_name,m_classnum,m_class);

db.ExecuteSQL(temp);

MessageBox("增加成功");

db.Close();

}


3.修改密码
void CChangePassword::OnButton2()
{
   UpdateData(TRUE);      
   CDatabase db1;
db1.Open(_T("socc"),FALSE,FALSE,_T("ODBC;"),FALSE);
CString temp1,temp3,temp4,temp7;
temp7.Format("select * from password where flag=%d",1);
CRecordset rs1(&db1);
rs1.Open(AFX_DB_USE_DEFAULT_TYPE,temp7);
rs1.GetFieldValue("学号",temp3);
   temp1.Format("select * from password where 学号=%s",temp3);
CRecordset rs2(&db1);
rs2.Open(AFX_DB_USE_DEFAULT_TYPE,temp1);
rs2.GetFieldValue("密码",temp4);
if(temp4!=m_oddpw)
{
            MessageBox("原密码错误");
       }
else
{

 if(m_newpw!=m_newpw2)
        {
        MessageBox("两次新密码输入不一致,请确认后再输入");
        }
 else
{
   CString temp,temp2;
       temp2.Format("select * from password where flag=%d",1);
       CRecordset rs1(&db1);
       rs1.Open(AFX_DB_USE_DEFAULT_TYPE,temp2);
       rs1.GetFieldValue("学号",temp3);
   temp.Format("update password set 密码='%s' where 学号=%s",m_newpw2,temp3);
        db1.ExecuteSQL(temp);
MessageBox("更改成功");OnOK();
}
}
return;
}

4.增加课程
void CEditCourse::OnAdd1()
{ UpdateData(TRUE);
if(m_coursenumber=="")
{
MessageBox("请输入你要增加课程的课程号");
return;
}
UpdateData(TRUE);
if(m_coursenumber=="" || m_coursename=="" || m_courseteacher=="" || m_courseaddr=="" || m_coursetime=="" || m_score=="")
{
MessageBox("请输入完整的信息!!!");
return;
}
CDatabase db;
db.Open(_T("socc"),FALSE,FALSE,_T("ODBC;"),FALSE);
CString temp,temp1,temp2;
temp2.Format("select * from course where 课程号=%s",m_coursenumber);
CRecordset rs(&db);
rs.Open(AFX_DB_USE_DEFAULT_TYPE,temp2);
   if(!rs.IsEOF())
{MessageBox("此课程已有,请查清后再输!!!");return;
}
temp.Format("insert into course (课程号,课程名,教师名,上课地点,课程时间,课程学分) values('%s','%s','%s','%s','%s','%s')",m_coursenumber,m_coursename,m_courseteacher,m_courseaddr,m_coursetime,m_score);
   db.ExecuteSQL(temp);
temp1.Format("insert into StuCouAve (课程号) values('%s')",m_coursenumber);
   db.ExecuteSQL(temp1);
db.Close();
MessageBox("增加成功");
}

5.录入成绩:

void CInputScore1::OnEnsure()
{   UpdateData(TRUE);
if(m_coursecode=="")
{
MessageBox("请输入要录入成绩的课程号");
return;
}
CDatabase db;
db.Open(_T("socc"),FALSE,FALSE,_T("ODBC;"),FALSE);
CString temp,temp1,temp2,temp3,temp4,temp5;
temp.Format("select * from StudentCourse where 课程号=%s",m_coursecode);
    CRecordset rs(&db);
rs.Open(AFX_DB_USE_DEFAULT_TYPE,temp);
if(rs.IsEOF())
{
MessageBox("该课程无人选修或无此课程,输入错误!");
return;
}
    rs.MoveFirst();
rs.GetFieldValue("学号",temp1);
temp2.Format("select * from student where 学号=%s",temp1);
CRecordset rs1(&db);
rs1.Open(AFX_DB_USE_DEFAULT_TYPE,temp2);
rs1.GetFieldValue("班级",temp3);
rs1.GetFieldValue("姓名",temp4);
m_number=temp1;
m_class=temp3;
m_name=temp4;
UpdateData(FALSE);
XueHao=temp1;
db.Close();
}
6.查询课程
BOOL CSearchCourse::OnInitDialog()
{
CDialog::OnInitDialog();

// TODO: Add extra initialization here
m_list.InsertColumn(0,"课程代码",LVCFMT_CENTER,80,-1);
m_list.InsertColumn(1,"课程名称",LVCFMT_CENTER,80,-1);
m_list.InsertColumn(2,"人数",LVCFMT_CENTER,80,-1);
m_list.InsertColumn(3,"学分",LVCFMT_CENTER,80,-1);
return TRUE;  // return TRUE unless you set the focus to a control
             // EXCEPTION: OCX Property Pages should return FALSE
}


4.数据库设计

4.1 概念结构设计

根据需求分析阶段得到的数据字典以及数据流图,由以上分析可以得到系统中出现的实体有:学生信息实体、课程信息实体等等。  可以画出对应的E-R图如下:


spacer.gif

spacer.gifspacer.gif

spacer.gif


spacer.gifspacer.gifspacer.gif

spacer.gifspacer.gifspacer.gif

spacer.gifspacer.gifspacer.gif

spacer.gifspacer.gif


spacer.gifspacer.gif





 图2 学生信息实体E-R图



spacer.gif

spacer.gif


spacer.gifspacer.gif

spacer.gifspacer.gif

spacer.gif

spacer.gifspacer.gif














spacer.gifspacer.gif


spacer.gifspacer.gif

spacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gifspacer.gif

spacer.gifspacer.gif编号

spacer.gif








spacer.gif

spacer.gifspacer.gifspacer.gif

spacer.gif


spacer.gif

spacer.gif




5学生成绩实体E-R图

4.2 逻辑结构设计

根据上面概念结构设计阶段得到的部分E-R图,下一步应该将它转化为关系模型。可以得到对应的关系模式为:

学生信息(学号、姓名、班级、已选课数

管理员信息(管理员号、姓名、性别、出生日期)

课程信息(课程号、课程名、课程学分、教师名、上课地点、课程时间、已报人数、限报人数

选课信息编号学号课程号、课程名、学分、成绩)

学生成绩编号、课程号、平均成绩)

spacer.gifspacer.gifspacer.gifspacer.gif4.3 物理结构设计

 4.3.1 建立各种表

create table course

(课程号   int  constraint s_prim  primary key,

课程名 varchar(20) not null,

教师名   varchar(20) ,

上课地点  varchar(20),

课程时间  varchar(20),

课程学分int,

已报人数int,

限报人数int,

)  

create table password

(学号int  primary key,

密码varchar(20) not null,

flagint ,

)

create table StuCouAve

(编号   int primary key,

课程号  int ,

平均成绩int,

)

create table  student

(姓名varchar(20) not null,

学号intprimary key,

班级varchar(20) ,

已选课数int,

)

create table StudentCourse

(编号varchar(20) primary key,

学号int  not null,

课程名varchar(20) ,

课程号int,

学分int,

成绩int,


)


5.运行结构和测试

5.1运行界面极其效果图

  图5.1学生登录界面:

spacer.gif


5.1.1当输入密码错误时:             图5.1.2 当输入的学生不存在时:


spacer.gifspacer.gif

5.2学生操作界面:

spacer.gif


5.2.1选课界面 :                            图5.2.2 修改密码:


spacer.gifspacer.gif

5.2.3 查询及退选已选课程


spacer.gif

5.3 管理员登陆

spacer.gif

5.4 管理员操作平台

spacer.gif

5.4.1 增加学生

spacer.gif

5.4.2 录入成绩

spacer.gif

5.4.3 查询选课情况

spacer.gif

5.4.4 编辑课程

spacer.gif

 5.2问题说明

    1.数据库及表建立好之后,出现的最大问题是向vc++中倒数据源出现错误,经过查询资料,找老师帮忙,终于连通。并且,通过此操作,学会了ADO数据绑定技术:

在 Visual C++ 中使用 ADO 数据绑定

u 使用“MFC 应用程序向导”创建 MFC 对话框应用程序或 MFC Formview 应用程序。

u 将 Microsoft ADO 数据控件添加到对话框;

u 将 ADO 数据控件指向 OLE DB 数据源。

a. 右击 ADO 数据控件,再单击“属性”。

b. 在“控件”选项卡上,单击“使用连接字符串”。可以使用提供的提供程序也可以删除它。

c. 单击“生成”。如果从“使用连接字符串”中删除了提供程序,现在可以定义一个。定义提供程序后,再次访问 ADO 数据控件的属性,然后再次选择“生成”继续。

如果在选择“生成”之前在“使用连接字符串”中定义了提供程序,现在可以定义数据链接属性。这将显示“DataLink 向导”。

d. 如有必要更改“提供程序”,并为提供程序定义适当的“位置”和“数据源”值。例如,如果使用的是 SQL Server 提供程序,则“位置”指定数据库服务器,而“数据源”指定数据库。如果使用的是 ODBC 提供程序,则“数据源”对应于 ODBC DSN。

e. 如果数据源需要,单击“身份验证”选项卡并设置“用户名”和“密码”的值。

f. 单击“连接”选项卡,再单击“测试连接”测试数据源。滚动到“结果”窗口的最后,查看是否通过了测试。如果测试失败,检查数据源的配置。常见错误包括无效的密码以及“位置”和“数据源”字段的值不正确。

g. 退出“DataLink 向导”,返回到 ADO 数据控件的属性表。

1. RecordSource 选项卡中,将查询输入到“命令文本 (SQL)”中。数据绑定控件可绑定到此查询的结果。查询通常为 SQL。但是,某些 OLE DB 提供程序不使用 SQL。

2. 设置所需的任何其他 ADO 数据控件属性,然后关闭 ADO 数据控件的属性表。

3. 添加数据绑定控件。例如,添加 DataGrid 控件,它不同于 RDO DBGrid 控件。

4. 设置 DataGrid 的属性。

a. 右击 DataGrid,再单击“属性”。

b. 单击“所有”选项卡,然后将 DataSource 属性设置为 ADO 数据控件。单击“数据源”下拉列表,找到 ADO 数据控件的 ID。默认的 ID 名称为 IDC_ADODC1。

若要以测试模式运行,请按 Ctrl+T。您将能够在所有数据中滚动。按 Esc 键或关闭对话框以结束测试模式。

2.管理员的输入成绩功能出现问题,经检验,是sql语言的编写问题,最后在查找资料,老师帮助下,终于解决

  图5.2.1 输入成绩错误

spacer.gif


6.课程设计总结与体会

6.1系统实现的技术方案评价

通过本次课程设计,在小组的共同合作努力下,终于成功。编写代码的技术水平明显提高,sql语句的编写更是熟练。E-R图对于整个设计至关重要,是我们整个课程设计的灵魂。

6.2 软件质量评价

本次课程设计所做的学生选课系统,功能比较全面,界面友好,质量较好,适合各学校使用。

6.3 课程设计过程中软件开发时间分配评价

本次课程设计用时不到两周,第一周我们小组计划:

1.找资料;

2.数据库完成、E-R图设计完成。

寒假及第二周:

1.实现功能,界面设计;

2.完成实验报告。

所有工作基本都在指定时间,有特定的同学完美完成。通过此次试验,在认真分配任务后,课程设计高效、有序的完成,小组合作愉快。

6.4 经验与教训

加载测试工作贯穿于程序测试工作的全过程,整个录入、修改、查询、处理工作均可视为对数据库的加载测试工作。要设计出一个好的学生选课系统数据库,除满足系统所要求的功能外,还必须遵守下列原则:1)基本表的个数越少越好。2) 主键的个数越少越好。3)字段的个数越少越好。4) 所有基本表的设计均应尽量符合第三范式。

6.5 总结与体会

在做课程设计的过程中遇到很多问题,一开始时数据库中表与表的关系有点模糊,但经过多次做了之后对表的关系比较清晰,还有是在编写程序时,由于vc++了解的不是很透彻,编写起来有点困难,总是出错,经过调试后终于把错误慢慢减少了,通过这次课程设计收获了好多,能够熟悉地建数据库,写查询语句,其中最大的问题是vc++与SqlServer的整合。

由于本身能力的局限性,所以编写的代码,即使经过反复检查也难免出错所以在本阶段力求使用有限的时间找出尽可能多的错误,力求系统尽量正确。

7.参考材料

[1]数据库原理与应用:西安电子科技大学出版社高荣芳 2009.8

[2]Visual C++ 精彩实例详解机械工业出版社袁丁傅一平等 2001.9

[3]C++语言程序设计清华大学出版社郑莉董渊等 2002.6

[4]Visual C++程序设计例学与实践清华大学出版社魏亮李春葆 2008.6

[5]SQL SERVER 2000管理,开发及应用实例洋解:人民邮电出版社陈世洪 2004.8