概述

项目背景

随着我国教育体制改革的深入进行,教育系统得到了前所未有的发展。学生管理正在逐步迈向管理信息现代化。但是我国的学生管理信息化水平还处在初级阶段,主要表现在对学生的学籍信息管理还是采用原有的人工管理方式。学校的规模不断扩大,学生数量急剧增加,有关学生的各种信息量也成倍增长。由于大学生类别和专业的设置的多样化,大学生的学籍管理历来是非常繁琐和复杂的的工作。面对庞大的信息量, 这时的人工管理几乎无法实现,在这种情况下用数据库进行管理变的尤为必要,这可以发挥计算机的优势来提高学生管理工作的效率。通过这样的系统,可以做到信息的规范管理,科学统计和快速的查询,从而减少管理方面的工作量和人为错误。

编写目的

学生学籍管理系统是应对学生人数增多、信息量增大的问题,实现管理的现代化、化,逐步摆脱当前学生成绩管理的人工管理方式,提高成绩管理效率而开发的。望该开发程序能够解决学生信息存储、学生各种信息查询等一系列功能。

软件定义

学生信息管理系统是针对学校人事处的大量业务处理工作而开发的管理软件,主要用于学校学生信息管理,总体任务是实现学生信息关系的系统化、科学化、规范化和自动化,其主要任务是用计算机对学生各种信息进行日常管理,如查询、修改、增加、删除,另外还考虑到学生选课,针对这些要求设计了学生信息管理系统。

开发环境

开发环境:Windows XP、VC6.0 辅助工具:PowerDesigner 15 数据库管理系统:SQL Server 2000 运行环境:Windows 2000/XP/2003

需求分析

问题陈述

进行数据库设计首先必须准确了解用户需求,目的是为学籍管理数据库系统的设计打下牢牢的基础,是数据库开发的重要文件依据,主要为数据库设计人员使用,是用户和系统分析员的项目依据文件。需求分析是否做得充分与准确,它决定了在其上构建数据库大厦的速度和质量。

系统主要功能

(1)学生档案的管理,即录入、修改、查询、输出学生档案信息,这些信息包括学生基本情况、学生简历情况、学生奖励情况、学生处分情况、学生家庭信息、学生体检情况。 (2)学生学籍管理,录入、修改、查询、输出学生学籍信息,这些信息包括学生奖贷学金情况、学生注册、学生异动情况、学生军训情况、学生毕业情况。 (3)学生成绩管理,录入修改、查询、输出学生入校成绩,各学期、各门课程的成绩信息,并支持按年级、班级等条件的统计、查询、报表输出。

简要分析:

(1)学生简历情况和学生基本情况可以合为一张学生信息表 (2)学生奖励情况和处分情况可以合为一张表,增加一项用于表示“奖励”或“处罚” (3)学生军训情况可以作为一门课程,放入课程表中,无需单独设一张表 (4)学生毕业信息可以在学生表中增加一项简单表示,无需单设一张表

经过分析,为了表示要求的信息,本学生学籍信息管理系统可以抽象出8个主要实体:学生、奖励或处罚、家庭、体检、贷款、注册、异动、课程。

数据库概念结构设计

系统E-R图

下面是用PowerDesingner 15 设计出的系统CDM图,既概念模型图:

下面是用PowerDesingner 15 从CDM图直接导出的PDM图,即物理结构图:

数据库逻辑结构设计

逻辑结构设计就是把概念结构设计阶段设计好的基本E-R图转换为与选用DBMS产品所支持的数据模型相符合的逻辑结构。

关系表

通过上一步画出的E-R图即可得到对应的关系表,我们采用PowerDesigner直接得出对应的PDM图,双击PDM图中某个实体,在Preview中可以得到对应的Sql语句,在Sql Server 2000中打开查询分析器即可用相应的Sql语句即可得到初步的关系表。(此处省略。。。具体定义在最后的源码中)

定义视图

在设计表时,考虑到数据冗余,本系统只保留“学号”作为表间的连接。为了方便用户使用,可以把这些详细的信息用视图来表示,并且不会产生冗余,从而方便了用户的查询;由于本系统信息对管理员和学生都不是什么保密信息,所以无需考虑系统安全性而为不同级别用户再定义相应的视图;此外,为了符合用户习惯,我们在视图中使用中文别名。

(1)学生基本信息视图:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
USE Student
GO
CREATE VIEW StudentInfo
AS
  SELECT  StuNo 学号,StuName  姓名,StuSex  性别,StuBirthTime 出生日期,
          StuProvince  籍贯,StuNation 民族,StuFace 政治面貌,
          StuFromWhere 来源地区,StuBirthPlace 出生地,StuCollege 学院,
          StuMajor 专业,StuClass 行政班级,StuStudyTime 学制,
          StuSchoolTime 入学时间,StuCurrentClass 当前所在年级,
          StuDormitory 宿舍,StuEMail 电子邮件,StuPhone 联系电话,
          StuPost 邮编,StuID 身份证号,StuIsGraduate 是否毕业,
          StuGraduateDate 毕业日期
  FROM student

(2)学生异动信息视图:

1
2
3
4
5
6
7
8
9
USE Student
GO
CREATE VIEW StuChangeInfo
AS
  SELECT  StuChangeID 异动记录号,StuChange.StuNo 学号,StuName 姓名,
          StuCollege 学院,StuClass 班级,StuMajor 专业,StuChangeKind
          异动类型,StuChangeDate 异动日期,StuChangeDetail 异动详细描述
  FROM Student,StuChange
  where Student.StuNo=StuChange.StuNo

(3)学生课程信息视图:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
USE Student
GO
CREATE VIEW  StuCourseInfo
AS
  SELECT  StuCourseNo 课程编号,StuCourse.StuNo 学号,StuName 姓名,
          StuCollege 学院,StuClass 班级,StuMajor 专业,
          StuCourseYear 学年,StuCourseTerm 学期,
          StuCourseName 课程名,StuCourseScore 分数,
          StuCredit 已获学分,StuCourseJiDian 已获绩点,
          StuCourseKind 课程性质,StuReStudyFlag 重修标记,
          StuReStudyScore 重修分数,StuReTestFlag 补考标记,
          StuReTestScore 补考分数,StuCourseGS 课程归属,
          StuFXFlag 辅修标记
  FROM Student,StuCourse
  where Student.StuNo=StuCourse.StuNo

(4)学生体检信息视图:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
USE Student
GO
CREATE VIEW  StuHealthCheckInfo
AS
  SELECT  StuCheckID 体检编号,Student.StuNo 学号,StuName 姓名,
          StuSex 性别,StuCollege 学院,StuClass 班级,StuMajor 专业,
          StuPhone 联系电话,StuCheckYear 体检学年,StuCheckTerm
          体检学期,StuHeight 身高,StuWeight 体重,StuEye 视力,
          StuLungC 肺活量,StuBloodP 血压,StuLiver 肝功能,
          StuBlood 血常规,StuHeartLung 心肺功能,StuDiseaseItem
          异常项目,CheckConclusion 体检结果
  FROM Student,StudentHealthCheck
  where Student.StuNo=StudentHealthCheck.StuNo

(5)学生家庭信息视图:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
USE Student
GO
CREATE VIEW  StuFamilyInfo
AS
  SELECT  StuFamilyID 家庭编号,Student.StuNo 学号,StuName 姓名,
          StuCollege 学院,StuClass 班级,StuMajor 专业,
          StuFamilyAddress 家庭地址,StuFatherName 父亲姓名,
          StuFatherWP 父亲工作单位,StuFatherWPPost 父亲单位邮编,
          StuFatherPhone 父亲电话,StuMotherName 母亲姓名,
          StuMotherWP 母亲工作单位,StuMotherWPPost 母亲单位邮编,
          StuMotherPhone 母亲电话
  FROM Student,StuFamily
  where Student.StuNo=StuFamily.StuNo

(6)学生贷款信息视图:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
USE Student
GO
CREATE VIEW  StuLoanInfo
AS
  SELECT  StuLoanID 贷款编号,Student.StuNo 学号,StuName 姓名,
          StuCollege 学院,StuClass 班级,StuMajor 专业,
          StuLoanDate 贷款日期,StuLoanR 贷款原因,
          StuLoanNum 贷款数目,StuLoanBackNum 已还贷款数目,
          StuLoanIsBack 是否还清
  FROM Student,StuLoan
  where Student.StuNo=StuLoan.StuNo

(7)学生注册信息视图:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
USE Student
GO
CREATE VIEW  StuRegisterInfo
AS
  SELECT  StuRegisterID 注册编号,Student.StuNo 学号,StuName 姓名,
          StuCollege 学院,StuClass 班级,StuMajor 专业,
          StuCurrentClass 当前所在年级,StuRegisterYear 注册学年,
          StuRegisterTerm 注册学期,StuIsRegister 是否注册
  FROM Student,StuRegister
  where Student.StuNo=StuRegister.StuNo

(8)学生奖励或处罚视图:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
USE Student
GO
CREATE VIEW  StuRewardPunishInfo
AS
  SELECT  StuRPID 奖励或处罚记录号,Student.StuNo 学号,StuName 姓名,
          StuCollege 学院,StuClass 班级,StuMajor 专业,StuFace
          政治面貌,StuRPKind 奖励或处罚类型,StuRPDate 奖励或处罚日期,
          StuRPR 奖励或处罚原因,StuRP 奖励或处罚标记
  FROM Student,StuRewardPunish
  where Student.StuNo=StuRewardPunish.StuNo

定义索引

(1)所有表中的主键自动被设为索引项 (2)由于属性“学号”经常在连接操作中出现,所以在每张表中建立“学号”的索引 (3)课程表中的“分数”经常作为最大最小值被查询,可以建立相应索引

1
create index StuCourseScoreIndex on StuCourse(StuCourseScore)

定义权限

(1)当前用户为dbo,是系统管理员,可以通过sql语句赋予dbo对数据库Student中表student的所有特权,不过这是默认的,例如:

1
2
3
4
grant all privileges
on Student
to dbo
with grant option

(2)先在管理器中建立一个登录用户,再在Student数据库中建立一个用户sh,假设他是一名学生,则可以赋予他对所有表的select权限。

1
2
3
4
5
6
7
8
grant select on StuChange to sh;
grant select on StuCourse to sh;
grant select on Student to sh;
grant select on StudentHealthCheck to sh;
grant select on StuFamily to sh;
grant select on StuLoan to sh;
grant select on StuRegister to sh;
grant select on StuRewardPunish to sh;

定义触发器

各表之间只用“学号”作为连接,并已经用管理器建立了关系,无需再建立“学号”上的触发器,即无论在哪里修改“学号”,都会因为这种主键与外键的关系而失败,学生表中的“学号”总是与其他表中的“学号”保持一致的。

(1)课程表StuCourse

表中的重修、补考标记可能会与重修分数、补考分数不一致,即重修标记为“否”,但分数却有值,这是check约束无法约束的;同时,如果分数>=60,则重修和补考标记都应为“否”。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
CREATE trigger CourseReStudyTestFlag
on StuCourse
after insert,update
as
   if exists(select StuNo,StuCourseNo from StuCourse where
     StuReStudyFlag='否' or StuReTestFlag='否' or StuCourseScore>=60)
     begin
       update StuCourse set StuReStudyScore=null
       where StuReStudyFlag='否'

       update StuCourse set StuReTestScore=null
       where StuReTestFlag='否' 

       update StuCourse set StuReTestFlag='否'
       where StuCourseScore>=60

       update StuCourse set StuReStudyFlag='否'
       where StuCourseScore>=60
     end

(2)学生表Student

如果学生没有毕业,“毕业日期”一项应为空

1
2
3
4
5
6
7
8
9
CREATE trigger StuGraduate
on Student
for insert,update
as
   if  exists (select StuNo from Student where StuIsGraduate='否' )
      begin
        update Student set StuGraduateDate=null
        where StuIsGraduate='否'
      End

(3)学生贷款表StuLoan

如果已还贷款数目=贷款数目,“是否还清”一项应为“是”

1
2
3
4
5
6
7
8
9
create trigger StuLoanBack
on StuLoan
for insert,update
as
   if (select StuLoanBackNum from StuLoan)=
      (select StuLoanNum from StuLoan)
      begin
        update StuLoan set StuLoanIsBack='是'
      End

定义存储过程

(1)查询学生档案信息,包括学生基本情况、学生奖励情况、学生处分情况、学生家庭信息、学生体检情况。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
create procedure SelectDangAn
(@xuehao char(20))
As
   Begin
      select *
      from Student,StuRewardPunish,StuFamily,StudentHealthCheck
      where Student.StuNo=StuRewardPunish.StuNo and
      StuRewardPunish.StuNo=StuFamily.StuNo and
      StuFamily.StuNo=StudentHealthCheck.StuNo and
      StudentHealthCheck.StuNo=@xuehao
   End
Go
exec SelectDangAn @xuehao='20091602310073'

(2)查询学生学籍信息,包括学生贷款情况、学生注册情况、学生异动情况、学生毕业情况。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
create procedure SelectXueJi
(@xuehao char(20))
as
   begin
      select *
      from Student,StuLoan,StuRegister,StuChange
      where Student.StuNo=StuLoan.StuNo and
      StuLoan.StuNo=StuRegister.StuNo and
      StuRegister.StuNo=StuChange.StuNo and
      StuChange.StuNo=@xuehao
   end
go
exec SelectXueJi @xuehao='20091602310073'

(3)查询学生各门课成绩,支持按年级和班级条件查询。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
create procedure SelectChengJi1
(@xuehao char(20))
as
   begin
      select *
      from Student,StuCourse
      where Student.StuNo=StuCourse.StuNo and
      StuCourse.StuNo=@xuehao
   end
go
exec SelectChengJi @xuehao='20091602310073'

create procedure SelectChengJi2
(@class char(30))
as
   begin
      select *
      from Student,StuCourse
      where Student.StuNo=StuCourse.StuNo and
      Student.StuClass=@class
   end
go
exec SelectChengJi2 @class='计算机科学与技术0903班'

数据流图及程序结构框图

顶级数据流图:

一级数据流图:

二级数据流图:

程序结构框图:

程序源代码及其说明

(1)引入ADO组件类型库,初始化组件

直接在Stdafx.h文件中加入下面语句来实现引入:

1
#import "C:\Program Files\Common Files\System\ado\msado15.dll"no_namespace rename("EOF","adoEOF")

语句no_namespace说明ADO对象不使用命名空间,rename (“EOF”, “adoEOF”)说明将ADO中结束标志EOF改为adoEOF,以避免和其它库中命名相冲突。

建立工作区Student,在CStudentApp类中的InitInstance()中初始化COM,如下:

1
CoInitialize(NULL);

在类CStudentApp中新建虚函数virtual int ExitInstance()用于关闭COM,如下:

1
2
3
4
5
int CStudentApp::ExitInstance()
{
    CoUninitialize();
    return CWinApp::ExitInstance();
}

接着就可以直接使用Ado提供的指针m_pConnection,m_pRecordset操作数据库了

(2)初始化界面

学生管理信息系统的程序结构中主要有三大组成部分:档案管理、学籍管理、成绩管理,其中每个模块都要实现相同的功能:录入、修改、查询、删除、输出,而“用户管理”模块可以忽略,故主要选择其中“档案管理”的“学生基本信息管理”来介绍代码部分。

主界面——学生档案管理界面:

学生基本信息界面:

说明:在主界面中,可以看到学生的整体档案信息,但必须是基本信息、奖励或处罚信息、家庭信息、体检信息都有才能显示;通过主界面的下面四个按钮可以将学生档案信息分开管理。

先在“学生基本信息”类中添加如下代码:

1
2
 _RecordsetPtr m_pRecordset; //创建记录集对象
_ConnectionPtr m_pConnection;

初始化“学生基本信息”界面中List控件函数Refresh()如下:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
void CStuBasicInfo::Refresh()
{
    //连接数据库,ADO方法
    //假设m_pConnection是我们已经建立好的连接,我们使用_RecordsetPtr接口的Open方法打开表的记录集

    _variant_t value;
    CString da;
    da="select * from StudentInfo";
    try
    {
        CoInitialize(NULL);
        m_pConnection.CreateInstance(_uuidof(Connection));
        m_pRecordset.CreateInstance(_uuidof(Recordset));

        m_pConnection->Open((_bstr_t)scon,"","",adModeUnknown);
        m_pRecordset->Open((_bstr_t)da,m_pConnection.GetInterfacePtr(),adOpenDynamic,
        adLockOptimistic,adCmdText);
    }
    catch (_com_error e)
    {
        MessageBox(e.ErrorMessage());
    }

    //list控件中初始化档案信息
    try
    {
        if(!m_pRecordset->BOF)
            m_pRecordset->MoveFirst();//记录指针移到第一行(第一条记录)
        else
        {
            AfxMessageBox("数据库中没有数据!");
            return ;
        }
        
        int count=0;//记录列数
        
        //listctrl中添加数据
        //如果没有遇到表结束标志adoEOF,则用GetCollect(字段名)来获取当前记录
        //指针所指的字段值,然后再用MoveNext()方法移动到下一条记录位置
        while(!m_pRecordset->adoEOF)
        {
            value = m_pRecordset->GetCollect("学号");
            m_list.InsertItem(count,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("姓名");
            m_list.SetItemText(count,1,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("性别");
            m_list.SetItemText(count,2,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("出生日期");
            m_list.SetItemText(count,3,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("籍贯");
            m_list.SetItemText(count,4,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("民族");
            m_list.SetItemText(count,5,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("政治面貌");
            m_list.SetItemText(count,6,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("来源地区");
            m_list.SetItemText(count,7,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("出生地");
            m_list.SetItemText(count,8,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("学院");
            m_list.SetItemText(count,9,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("专业");
            m_list.SetItemText(count,10,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("行政班级");
            m_list.SetItemText(count,11,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("学制");
            m_list.SetItemText(count,12,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("入学时间");
            m_list.SetItemText(count,13,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("当前年级");
            m_list.SetItemText(count,14,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("宿舍");
            m_list.SetItemText(count,15,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("电子邮件");
            if(value.vt==VT_NULL)
                m_list.SetItemText(count,16,"");
            else
                 m_list.SetItemText(count,16,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("联系电话");
            if(value.vt==VT_NULL)
                m_list.SetItemText(count,17,"");
            else
                m_list.SetItemText(count,17,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("邮编");
            if(value.vt==VT_NULL)
                m_list.SetItemText(count,18,"");
            else
                m_list.SetItemText(count,18,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("身份证号");
            m_list.SetItemText(count,19,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("是否毕业");
            m_list.SetItemText(count,20,(LPCSTR)(_bstr_t)value);

            value = m_pRecordset->GetCollect("毕业日期");
            if(value.vt==VT_NULL)
                m_list.SetItemText(count,21,"");
            else
                m_list.SetItemText(count,21,(LPCSTR)(_bstr_t)value);            

            count++;
            m_pRecordset->MoveNext();
        }
    }
    catch (_com_error e)
    {
        AfxMessageBox(e.ErrorMessage());
    }
}

(3)添加新纪录

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
void CStuBasicInfo::OnBUTTONAdd() 
{
    // TODO: Add your control notification handler code here

    //连接数据库,ADO方法
    //假设m_pConnection是我们已经建立好的连接,我们使用_RecordsetPtr接口的Open方法打开表的记录集

    _variant_t value;
    CString da;
    da="select * from StudentInfo";
    try
    {
        CoInitialize(NULL);
        m_pConnection.CreateInstance(_uuidof(Connection));
        m_pRecordset.CreateInstance(_uuidof(Recordset));

        m_pConnection->Open((_bstr_t)scon,"","",adModeUnknown);
        m_pRecordset->Open((_bstr_t)da,m_pConnection.GetInterfacePtr(),adOpenDynamic,
        adLockOptimistic,adCmdText);
    }
    catch (_com_error e)
    {
        MessageBox(e.ErrorMessage());
    }

    //写入数据
    try
    {
            UpdateData(true);
            m_pRecordset->MoveLast();
            m_pRecordset->AddNew();

            _variant_t b;
            b.vt=NULL;//空指针,用于向数据库中插入
    
            m_pRecordset->PutCollect("学号",(_variant_t)m_1);     
            m_pRecordset->PutCollect("姓名",(_variant_t)m_2);    
            m_pRecordset->PutCollect("性别",(_variant_t)m_3);    
            m_pRecordset->PutCollect("出生日期",(_variant_t)m_4);    
            m_pRecordset->PutCollect("籍贯",(_variant_t)m_5);    
            m_pRecordset->PutCollect("民族",(_variant_t)m_6);            
            m_pRecordset->PutCollect("政治面貌",(_variant_t)m_7);     
            m_pRecordset->PutCollect("来源地区",(_variant_t)m_8);    
            m_pRecordset->PutCollect("出生地",(_variant_t)m_9);    
            m_pRecordset->PutCollect("学院",(_variant_t)m_10);    
            m_pRecordset->PutCollect("专业",(_variant_t)m_11);    
            m_pRecordset->PutCollect("行政班级",(_variant_t)m_12);        
            m_pRecordset->PutCollect("学制",(_variant_t)m_13); 
            m_pRecordset->PutCollect("入学时间",(_variant_t)m_14);
            m_pRecordset->PutCollect("当前年级",(_variant_t)m_15);    
            m_pRecordset->PutCollect("宿舍",(_variant_t)m_16);
            
            if(m_17 == "")
                m_pRecordset->PutCollect("电子邮件",b);
            else
                m_pRecordset->PutCollect("电子邮件",(_variant_t)m_17);

            if(m_18 == "")
                m_pRecordset->PutCollect("联系电话",b);
            else
                m_pRecordset->PutCollect("联系电话",(_variant_t)m_18);

            if(m_19 == "")
                m_pRecordset->PutCollect("邮编",b);
            else    
                m_pRecordset->PutCollect("邮编",(_variant_t)m_19);    

            m_pRecordset->PutCollect("身份证号",(_variant_t)m_20);
            m_pRecordset->PutCollect("是否毕业",(_variant_t)m_21);
                 
            if(m_22 == "")
                m_pRecordset->PutCollect("毕业日期",b);
            else
                m_pRecordset->PutCollect("毕业日期",(_variant_t)m_22);

            m_pRecordset->Update();
    }
    catch (_com_error e)
    {
        AfxMessageBox(e.ErrorMessage());
    }
    m_list.DeleteAllItems();
    Refresh();
}

(4)修改记录部分

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
int selRow;
void CStuBasicInfo::OnBUTTONModify() 
{
    // TODO: Add your control notification handler code here

    int nItemSelected=m_list.GetSelectedCount();//所选表项数
    if(nItemSelected<1)
    {
        MessageBox("请先选择你要修改的项目");
        return;
    }
    if(nItemSelected>1)
    {
        MessageBox("只能同时修改一项");
        return;
    }
    selRow = m_list.GetNextItem(-1,LVNI_ALL|LVNI_SELECTED);//当前选取行号

    m_1 = m_list.GetItemText(selRow,0);
    m_2 = m_list.GetItemText(selRow,1);
    m_3 = m_list.GetItemText(selRow,2);
    m_4 = m_list.GetItemText(selRow,3);
    m_5 = m_list.GetItemText(selRow,4);
    m_6 = m_list.GetItemText(selRow,5);
    m_7 = m_list.GetItemText(selRow,6);
    m_8 = m_list.GetItemText(selRow,7);
    m_9 = m_list.GetItemText(selRow,8);
    m_10 = m_list.GetItemText(selRow,9);
    m_11 = m_list.GetItemText(selRow,10);
    m_12 = m_list.GetItemText(selRow,11);
    m_13 = m_list.GetItemText(selRow,12);
    m_14 = m_list.GetItemText(selRow,13);
    m_15 = m_list.GetItemText(selRow,14);
    m_16 = m_list.GetItemText(selRow,15);
    m_17 = m_list.GetItemText(selRow,16);
    m_18 = m_list.GetItemText(selRow,17);
    m_19 = m_list.GetItemText(selRow,18);
    m_20 = m_list.GetItemText(selRow,19);
    m_21 = m_list.GetItemText(selRow,20);
    m_22 = m_list.GetItemText(selRow,21);

    UpdateData(false);

    m_modifyOK.EnableWindow(true);

    
}

void CStuBasicInfo::OnBUTTONModifyOK() 
{
    // TODO: Add your control notification handler code here

    // TODO: Add your control notification handler code here
    //连接数据库,ADO方法
    //假设m_pConnection是我们已经建立好的连接
    //我们使用_RecordsetPtr接口的Open方法打开表的记录集

    _variant_t value;
    CString da;
    da="select * from StudentInfo";
    try
    {
        CoInitialize(NULL);
        m_pConnection.CreateInstance(_uuidof(Connection));
        m_pRecordset.CreateInstance(_uuidof(Recordset));

        m_pConnection->Open((_bstr_t)scon,"","",adModeUnknown);
        m_pRecordset->Open((_bstr_t)da,m_pConnection.GetInterfacePtr(),adOpenDynamic,
        adLockOptimistic,adCmdText);
    }
    catch (_com_error e)
    {
        MessageBox(e.ErrorMessage());
    }

    //写入数据
    try
    {
            UpdateData(true);
            m_pRecordset->Move(selRow);

            _variant_t b;
            b.vt=NULL;//空指针,用于向数据库中插入
    
            m_pRecordset->PutCollect("学号",(_variant_t)m_1);     
            m_pRecordset->PutCollect("姓名",(_variant_t)m_2);    
            m_pRecordset->PutCollect("性别",(_variant_t)m_3);    
            m_pRecordset->PutCollect("出生日期",(_variant_t)m_4);    
            m_pRecordset->PutCollect("籍贯",(_variant_t)m_5);    
            m_pRecordset->PutCollect("民族",(_variant_t)m_6);            
            m_pRecordset->PutCollect("政治面貌",(_variant_t)m_7);     
            m_pRecordset->PutCollect("来源地区",(_variant_t)m_8);    
            m_pRecordset->PutCollect("出生地",(_variant_t)m_9);    
            m_pRecordset->PutCollect("学院",(_variant_t)m_10);    
            m_pRecordset->PutCollect("专业",(_variant_t)m_11);    
            m_pRecordset->PutCollect("行政班级",(_variant_t)m_12);        
            m_pRecordset->PutCollect("学制",(_variant_t)m_13); 
            m_pRecordset->PutCollect("入学时间",(_variant_t)m_14);
            m_pRecordset->PutCollect("当前年级",(_variant_t)m_15);    
            m_pRecordset->PutCollect("宿舍",(_variant_t)m_16);
            
            if(m_17 == "")
                m_pRecordset->PutCollect("电子邮件",b);
            else
                m_pRecordset->PutCollect("电子邮件",(_variant_t)m_17);

            if(m_18 == "")
                m_pRecordset->PutCollect("联系电话",b);
            else
                m_pRecordset->PutCollect("联系电话",(_variant_t)m_18);

            if(m_19 == "")
                m_pRecordset->PutCollect("邮编",b);
            else    
                m_pRecordset->PutCollect("邮编",(_variant_t)m_19);    

            m_pRecordset->PutCollect("身份证号",(_variant_t)m_20);
            m_pRecordset->PutCollect("是否毕业",(_variant_t)m_21);
                 
            if(m_22 == "")
                m_pRecordset->PutCollect("毕业日期",b);
            else
                m_pRecordset->PutCollect("毕业日期",(_variant_t)m_22);

            m_pRecordset->Update();
    }
    catch (_com_error e)
    {
        AfxMessageBox(e.ErrorMessage());
    }

    m_list.DeleteAllItems();
    Refresh();
    OnBUTTONClear();
    m_modifyOK.EnableWindow(false);
}

(5)删除部分

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
void CStuBasicInfo::OnBUTTONDel() 
{
    // TODO: Add your control notification handler code here
    //连接数据库,ADO方法
    //假设m_pConnection是我们已经建立好的连接,我们使用_RecordsetPtr接口的Open方法打开表的记录集

    _variant_t value;
    CString da;
    da="select * from StudentInfo";
    try
    {
        CoInitialize(NULL);
        m_pConnection.CreateInstance(_uuidof(Connection));
        m_pRecordset.CreateInstance(_uuidof(Recordset));

        m_pConnection->Open((_bstr_t)scon,"","",adModeUnknown);
        m_pRecordset->Open((_bstr_t)da,m_pConnection.GetInterfacePtr(),adOpenDynamic,
        adLockOptimistic,adCmdText);
    }
    catch (_com_error e)
    {
        MessageBox(e.ErrorMessage());
    }

   int i,iState;
   int nItemSelected=m_list.GetSelectedCount();//所选表项数
   int nItemCount=m_list.GetItemCount();//表项总数

   if(nItemSelected<1)
       return;
   for(i=nItemCount-1;i>=0;i--)
   {
      iState=m_list.GetItemState(i,LVIS_SELECTED);
      if(iState!=0) 
      {
        try
        {
            m_pRecordset->Move(i);
            m_pRecordset->Delete(adAffectCurrent);
            m_pRecordset->Update();
        }
        catch(_com_error *e)
        {
             AfxMessageBox(e->ErrorMessage());
        }
      }
   }
   m_list.DeleteAllItems();
   Refresh();
}

(6)查询部分

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
void CStuBasicInfo::OnBUTTONSearch() 
{
    // TODO: Add your control notification handler code here

    UpdateData(true);
    if(m_1=="")
    {
        MessageBox("请输入学号进行查询");
        return;
    }
    else
    {
        int nn=m_list.GetItemCount();
        CString str;
        for(int i=0;i<nn;i++)
        {
            str=m_list.GetItemText(i,0);
            str.Replace(" ","");
            m_1.Replace(" ","");
            if(m_1==str)
            {    
            m_1 = m_list.GetItemText(i,0);
            m_2 = m_list.GetItemText(i,1);
            m_3 = m_list.GetItemText(i,2);
            m_4 = m_list.GetItemText(i,3);
            m_5 = m_list.GetItemText(i,4);
            m_6 = m_list.GetItemText(i,5);
            m_7 = m_list.GetItemText(i,6);
            m_8 = m_list.GetItemText(i,7);
            m_9 = m_list.GetItemText(i,8);
            m_10 = m_list.GetItemText(i,9);
            m_11 = m_list.GetItemText(i,10);
            m_12 = m_list.GetItemText(i,11);
            m_13 = m_list.GetItemText(i,12);
            m_14 = m_list.GetItemText(i,13);
            m_15 = m_list.GetItemText(i,14);
            m_16 = m_list.GetItemText(i,15);
            m_17 = m_list.GetItemText(i,16);
            m_18 = m_list.GetItemText(i,17);
            m_19 = m_list.GetItemText(i,18);
            m_20 = m_list.GetItemText(i,19);
            m_21 = m_list.GetItemText(i,20);
            m_22 = m_list.GetItemText(i,21);

            UpdateData(false);
            return;
            }
        }
        MessageBox("找不到记录!");
        OnBUTTONClear();
    }
}

总结

本次课程设计历时两周,现在很高兴完成了,真的学到了不少。完成之后,才发现数据库设计部分,从抽象实体到寻找关系,从学习PowerDesigner到优化触发器才是最难的部分。对于编程,其实核心代码很少,就用到Ado中的两个指针而已,但是通过编程现在终于会连接数据库了,以后可能还会学习ODBC,JDBC,DAO等,同时学习了一下VC的控件使用方法。总之,此次数据库课程设计算是对本学期实验的一次综合实践吧,不过的确花了我们很多的时间,毕竟时间有限,所以前台系统也只是粗略完成了部分功能,数据表项也许还存在不足之处有待完善。同时在此感谢老师一学期的悉心教诲,谢谢。

参考文献

[1] 王珊,萨师煊.《数据库系统概论》.高等教育出版社.2010 [2] 刘刀桂,孟繁晶.《Visual C++实践与提高 数据库篇》.中国铁道出版社.2001 [3] 启明工作室.《Visual C++ + SQLServer数据库应用系统开发与实例》.人民邮电出版社.2004

学生管理信息系统源码(VC6)