数据库课程设计实验报.doc
数据库课程设计实验报告题 目:学生信息管理系统班 级:_ _学 号:_ _姓 名:_ _指导老师:_评 分:_2013年1月5日一、 工具介绍前台使用的工具是Qt,后台使用的是SQL Server 2008。这里主要介绍Qt。Qt是诺基亚开发的一个跨平台的C+图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt很容易扩展,并且允许真正地组件编程。优良的跨平台特性:Qt支持下列操作系统: Microsoft Windows 95/98, Microsoft Windows NT, Linux, Solaris, SunOS, HP-UX, Digital UNIX (OSF/1, Tru64), Irix, FreeBSD, BSD/OS, SCO, AIX, OS390,QNX 等等。面向对象Qt 的良好封装机制使得 Qt 的模块化程度非常高,可重用性较好,对于用户开发来说是非常方便的。 Qt 提供了一种称为 signals/slots 的安全类型来替代 callback,这使得各个元件之间的协同工作变得十分简单。二、系统需求分析学校每年都有新生入学、老生毕业,还有其他各种人事变动。如何有效地管理这些学生的信息,帮助学校和名师掌握学生的情况,这就是学生信息管理系统需要完成的功能。1.1 系统功能分析本系统主要的功能是收集学生的个人信息,以便向教师提供每个学生在校的情况。系统的主要功能有:l 学生个人信息输入,包括:姓名、性别、院系、生日、籍贯、生源所在地等。l 学生流动情况的输入,包括:转系、休学、复学、退学、毕业。l 奖惩情况的输入。l 学生个人情况查询和修改,包括流动情况和奖罚情况。1.2系统功能模块设计(划分)根据系统功能要求可以将系统分解成几个模块来分别设计应用程序界面学生信息管理系统普通用户管理员学生个人信息查询全部信息查询学生信息管理奖励情况管理学籍变更情况管理处罚情况管理选择登录模块 1.3 与其它系统的关系学生信息管理系统是校园信息管理系统的一个组成部分。它为其它系统,如班级信息管理系统、教学管理系统、成绩单系统、宿舍分配系统等,提供学生的基本情况。同时需要其他系统提供的班级设置和院系设置等情况。这些系统可以使用同一个数据库,直接相互调用所需的数据。1.4 数据流程图学生信息管理系统的数据流程如图2所示。图2、学生信息管理系统数据流程图三、数据库设计A. 数据需求(1)、数据字典表1 STUDENT学生个人信息表字段名数据类型是否可空说明stu_idchar(10) N学号(主关键字)namechar(20)Y姓名sexchar(1)Y性别(M、F)class_idchar(5)Y班级编号(外部关键字)depart_idchar(5)Y所属院系编号(外部关键字)birthdateY生日NATIVE_PLACEchar(20)Y籍贯表2 CHANGE学籍变更信息表字段名数据类型是否可空说明change_idchar(5)N记录号(主关键字)stu_idchar(10)Y学号(外部关键字)CHANGEintY变更代码(外部关键字)REC_TIMEDATEY记录时间DESCRIPTchar(20)Y描述表3 REWARD奖励记录信息表字段名数据类型是否可空说明reward_idchar(5)N记录号(主关键字)stu_idchar(10)Y学号(外部关键字)level_idintY级别代码(外部关键字)REC_TIMEdateY记录时间DESCRIPTchar(20)Y描述表4 PUNISHMENT处罚记录信息表字段名数据类型是否可空说明punish_idchar(5)N记录号(主关键字)stu_idchar(10)Y学号(外部关键字)level_idintY级别代码(外部关键字)REC_TIMEdateY记录时间shengxiaochar(1)Y是否生效(T、F)DESCRIPTchar(20)Y描述表5 DEPARTMENT院系信息表字段名数据类型是否可空说明depart_idchar(5)N编号(主关键字)NAMEchar(20)Y全称表6 CLASS班级信息表字段名数据类型是否可空说明class_idchar(5)N编号(主关键字)NAMEchar(20)Y全称MONITORchar(10)Y班长学号(外部关键字)表7 CHANGE_CODE学籍变动代码表字段名数据类型是否可空说明CODEintN代码(主关键字)DESCRIPTchar(20)Y描述表8 REWARD_LEVELS奖励等级代码表字段名数据类型是否可空说明CODEintN代码(主关键字)DESCRIPTchar(20)Y描述表9 PUNISH_LEVELS处罚等级代码表字段名数据类型是否可空说明CODEintN代码(主关键字)DESCRIPTchar(20)Y描述B、数据库概念结构设计下图是本系统所需数据的E-R模型图。学生班级院系系系学号性别生日籍贯姓名班级系别班号班名系名系号组成组成学生信息管理系统学籍情况奖励情况处罚情况管理成管理成管理等级描述描述等级等级描述管理成管理成管理成编号编号编号编号C、数据库的建立create database stuuse stu/创建学生个人信息表create table stu(stu_id char(10), name char(20), sex char(1), class_id char(5), depart_id char(5), brith date, native_place char(20),primary key(stu_id),check(sex in('M','F')/创建change学籍变更表create table change(change_id char(5), stu_id char(10), change int, rec_time date, descript char(20), primary key(change_id)/创建reward奖励记录表create table reward(reward_id char(5), stu_id char(10), level_id int, rec_time date, primary key(reward_id)/创建惩罚记录信息表drop table punishcreate table punish(punish_id char(5), stu_id char(10), level_id int, rec_time date, shengxiao char(1), descript char(10), primary key(punish_id), check(shengxiao in('T', 'F')/创建院系表create table depart(depart_id char(5), name char(20) not null, primary key (depart_id)/班级信息表create table class(class_id char(5), name char(20) not null, monitor_id char(10), primary key(class_id)/学籍变更表create table change_code(code int, descript char(20), primary key(code)/奖励等级表create table reward_levels(code int, descript char(20), primary key(code)/处罚等级表create table punish_levels(code int, descript char(20), primary key(code)/创建索引create index stu_index on stu(stu_id)create index change_index on change(change_id)create index change_code_index on change_code(code)create index class_index on class(class_id)create index depart_index on depart(depart_id)create index punish_index on punish(punish_id)create index punish_levels_index on punish_levels(code)create index rewaed_index on reward(reward_id)create index reward_levels_index on reward_levels(code)/增加约束alter table stuadd foreign key (class_id) references class(class_id)alter table stuadd foreign key (depart_id) references depart(depart_id)/changealter table changeadd foreign key (stu_id) references stu(stu_id)alter table changeadd foreign key (change) references change_code(code)/reawrdalter table rewardadd foreign key (stu_id) references stu(stu_id)alter table rewardadd foreign key (level_id) references reward_levels(code)/punishalter table punishadd foreign key (stu_id) references stu(stu_id)alter table punishadd foreign key (level_id) references punish_levels(code)/classalter table classadd foreign key (monitor_id) references stu(stu_id)/更改stu表格中的数据类型alter table stu add birth datetimealter table stu alter column birth datetime/变更视图 drop view stu_changeselect stu.name as stu_name, class.name as class_name, depart.name as depart_namefrom stu, class, depart create view stu_changeas select stu.stu_id as '学号', stu.name as '姓名', sex as '性别', class.name as '班级', depart.name as '系部',change.change_id as '变更号', change.descript as '变更描述', change_code.descript as '变更代码描述'from stu, change, change_code, class, departwhere stu.stu_id = change.stu_id and change.change = change_code.code andstu.class_id = class.class_id and stu.depart_id = depart.depart_id/奖励视图drop view stu_rewardcreate view stu_rewardas select stu.stu_id as '学号', stu.name as '姓名', sex as '性别', class.name as '班级', depart.name as '系部',reward.level_id as '奖励序号', reward.descript as '奖励描述', reward_levels.descript as '奖励级别描述'from stu, reward, reward_levels, class, departwhere stu.stu_id = reward.stu_id and reward.level_id = reward_levels.code andstu.class_id = class.class_id and stu.depart_id = depart.depart_id/惩罚视图drop view stu_punishcreate view stu_punishas select stu.stu_id as '学号', stu.name as '姓名', sex as '性别', class.name as '班级', depart.name as '系部',punish.level_id as '惩罚序号', punish.descript as '惩罚描述', punish_levels.descript as '惩罚级别描述'from stu, punish, punish_levels, class, departwhere stu.stu_id = punish.stu_id and punish.level_id = punish_levels.code andstu.class_id = class.class_id and stu.depart_id = depart.depart_id本系统中所用到的学籍变更和奖惩级别代码如表10至表12所示(请设计者完成这些数据表的逻辑结构)。表10 学籍变更代码表代码说明0转系1休学2复学3退学4毕业表11 奖励级别代码代码说明0校特等奖学金1校一等奖学金2校二等奖学金3校三等奖学金4系一等奖学金5系二等奖学金6系三等奖学金表12 处罚级别代码代码说明0警告1严重警告2记过3记大过4开除四、各功能模块的设计与实现1功能模块说明1、登录2、学生个人信息输入3、学籍变更情况的输入4、奖历情况的输入5、处罚情况的输入6、学生个人情况查询和修改2、功能实现1) 登录界面如下说明:当前页面提供2个用户类型供选择。当用户选择普通用户时,登录模块下面的下拉列表的内容是禁用的,用户不可以选择。只有选择以管理员用户登录才可以选择下拉列表里面的内容。部分代码:connect(ui->user_comboBox,SIGNAL(currentIndexChanged(int),this, SLOT(setCurrentIndex(int);void Login:setCurrentIndex(int index) if(0 = index) ui->comboBox->setEnabled(false); else ui->comboBox->setEnabled(true); 这个代码完成的功能是当用户类型下拉列表控件中的索引改变(也就是下拉列表的内容改变)时,就激活当前窗口调用setCurrentIndex(int index),从而成功的实现对登录模块的禁用或者解除。2) 学生个人信息输入、学籍变更、处罚以及奖励信息输入界面如下:为了简约起见,我把四个模块的输入信息都集中在一个界面上(此处要用管理员账号登陆)。界面说明:此处用了四个QGroupBox控件,代表四个模块。再把各个模块所需要的控件放到上面。四个控件的初始状态都是禁用的(此时在它上面的控件也不能用,直到该控件被激活其它控件才可用)。当用户在登陆界面时选择登陆哪个模块,哪个模块的QGroupBox控件才被激活,上面的控件也就可以用了。当用户把信息输入正确完整,再按确定就可以提交给数据库。部分代码连结数据库代码:/打开连接数据库 QSqlDatabase db=QSqlDatabase:addDatabase("QODBC"); db.setDatabaseName(QString("DRIVER=SQL SERVER;" "SERVER=%1;" /服务器名称 "DATABASE=%2;"/数据库名 "UID=%3;" /登录名 "PWD=%4;" /密码 ).arg("HNQING-PC") .arg("stu") .arg("root") /hnQing-PC .arg("") );首先是选择数据库驱动(QODBC代表的是SQL server),然后依次设置服务器名、数据库名、登陆名、密码。connect(ui->submitButton, SIGNAL(clicked(), this, SLOT(stuSubmit(); /提交学生信息void InputInformation:stuSubmit() /提交学生基本信息 QSqlTableModel model; model.setTable("stu"); int row = model.rowCount(); /获取数据库的行数 if(!ui->stuEdit->text().isEmpty() && !ui->classEdit->text().isEmpty() && !ui->departEdit->text().isEmpty() b_submit = true; else b_submit = false; QMessageBox:warning(this, tr("warning"), tr("学号、班级名或系名不能为空!"); if(b_submit) model.insertRows(row, 1); model.setData(model.index(row, 0), ui->stuEdit->text(); model.setData(model.index(row, 1), ui->nameEdit->text(); model.setData(model.index(row, 2), ui->sexEdit->text(); model.setData(model.index(row, 3), ui->classEdit->text(); model.setData(model.index(row, 4), ui->departEdit->text(); model.setData(model.index(row, 5), ui->birthEdit->text(); model.setData(model.index(row, 6), ui->placeEdit->text(); /提交全部 if(model.submitAll() QMessageBox:about(this, tr("Submit"), tr("提交数据成功!"); /清空 b_submit = false; ui->stuEdit->clear(); ui->nameEdit->clear(); ui->sexEdit->clear(); ui->classEdit->clear(); ui->departEdit->clear(); ui->birthEdit->clear(); ui->placeEdit->clear(); else QMessageBox:critical(this, tr("Submit Error"), tr("提交数据失败!"); 此处使用Qt封装的类QSqlTableModel来实现与数据库的交互,提交成功后把输入框中的内容清空,并提示提交成功。否则提示提交失败(此时为清空输入框中的内容)。其它模块和这个差不多,代码就不贴出来了。3) 个人信息查询和修改界面如下此处用QTableView控件来显示数据库中的内容。用QTabWidget来实现像QQ那样的效果,可以分组,节省了很大的空间,这样就可以把查询删除相关的空间放到相应的页面上,具有很好的用户友好性。它根据用户选择的数据表格和打开方式来确定表格中的内容是否可以编辑,编辑后的内容会同步到后台的服务器。此中的增加记录和删除记录,下面还提供各种表格的查询和删除,以及视图查询。按表格查询:视图查询:部分代码:/动态显示数据库中的内容connect(ui->cancelButton, SIGNAL(clicked(), this, SLOT(close();void stu_information:okSlot() if(ui->readRadio->isChecked() b_edit = false; if(ui->EditRadio->isChecked() b_edit = true; if(b_edit = false) ui->tableView->setEditTriggers(QAbstractItemView:NoEditTriggers); else ui->tableView->setEditTriggers(QAbstractItemView:AllEditTriggers); int cnt = ui->comboBox->currentIndex(); setModelHeaderData(cnt);/设置tableview的水平标题void stu_information:setModelHeaderData(int cnt) switch(cnt) case 0: /学生个人信息表 model->setTable("stu"); /选择学生个人信息表 model->select(); ui->tableView->setModel(model); ui->tableView->show(); /设置表的标题 model->setHeaderData(0, Qt:Horizontal, tr("学号"); model->setHeaderData(1, Qt:Horizontal, tr("姓名"); model->setHeaderData(2, Qt:Horizontal, tr("性别"); model->setHeaderData(3, Qt:Horizontal, tr("班级号"); model->setHeaderData(4, Qt:Horizontal, tr("系部号"); model->setHeaderData(5, Qt:Horizontal, tr("生日"); model->setHeaderData(6, Qt:Horizontal, tr("籍贯"); break; /学生基本信息查询void stu_information:searchSlot() setModelHeaderData(0); int index = ui->search_ComboBox->currentIndex(); /获取当前下了列表的字符串 switch(index) case 0: str_field = "stu_id=" break; case 1: str_field = "name=" break; case 2: str_field = "sex=" break; case 3: str_field = "class_id=" break; case 4: str_field = "depart_id=" break; default: break; str_condition = ui->search_lineEdit->text(); QString str = str_field + + "'" + str_condition+ "'" qDebug() << model->tableName() << endl; model->setFilter(str); model->setSort(index, Qt:DescendingOrder); model->select(); ui->tableView->show();/删除void stu_information:deleteSlot() QSqlQuery query; setModelHeaderData(0); int index = ui->search_ComboBox->currentIndex(); /获取当前下了列表的字符串 switch(index) case 0: str_field = "stu_id=" break; case 1: str_field = "name=" break; case 2: str_field = "sex=" break; case 3: str_field = "class_id=" break; case 4: str_field = "depart_id=" break; str_condition = ui->search_lineEdit->text(); QString str = str_field + + "'" + str_condition+ "'" query.exec(tr("delete from stu where %1").arg(str); model->select(); ui->tableView->show();/视图查询void stu_information:viewButtonSlot() int index = ui->viewcomboBox->currentIndex(); switch(index) case 0: model->setTable("stu_change"); ui->tableView->setModel(model); str_condition = "'" + ui->view_lineEdit->text() + "'" model->setFilter(tr("stu_change.学号 = %1").arg(str_condition); model->select(); break;该段代码实现学生基本信息的查询和删除,以及视图查询。主要用到了QSqlTableModel类和QSqlQuery类来实现数据库的交互。五、总结1. 由于数据库两个表的外键的关联作用,开始创建的时候只能先建立数据库表,而不设置外键。等到把所有的表格建立好后,再添加约束。但是在删除记录时,同时又会出现错误。因为两个表之间外键和主键联系,导致无法删除,此时应该设计他们的关系为级联就可以了。2. 还有就是Qt界面文件编译后,如果再次修改可能出现意外错误,这个可能是Qt缺陷,要用记事本打开Qt界面文件把“class”之间的名字改成和你在源文件中命名的名字一样的才可以。开始我自己一直在找错误,找了很久没解决,后面在网上查,结果发现有人和我碰到一样的错误。又一次感觉网络的强大。3. 还碰到一个问题,像QSqlTableModel在该实例中,我定义成了局部变量。结果QTableView中没有显示。后面调试了才知道。是局部变量的原因,被销毁了。把它定义成指针或者成员变量就可以完美解决。对于这些大的程序,对一些关键变量的定义成局部的还是全局的显得很重要。4. 对于改程序,界面上含有的控件比较多。不对其进行重新命名的话。则代码的可读性不强。若重新命名则对名字的把握显得很重要,要么就会出现重名或者明出来的名字可读性不强。5. 这次感觉用到了一些软件工程的知识。做稍微大点的系统,要先做需求分析,然后建立模型,再划分各个子模块。先实现一个一个的模块,最后再把各个模块综合起来,此时测试的是各个模块的关联性。6. 通过这次课程设计,感觉自己的c+知识学习的还不是很好,面向对象的思想还不够深厚。扩展性不是很强。以后这方面还得多加学习才行。还有就是巩固了数据库的相关知识,尤其是对一些常用的SQL语句比较熟悉了。也觉察到了数据库的重要性,以及它在日常生活中所发挥的重要。7. 最后还要感谢我的团队成员高远和罗海的给力配合,我们保持着默契,才能顺利完成这次大作业。还要感谢老师和同学的帮助。