数据库课程设计报告

更新时间:2023-06-07 10:41:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

计算机学院 数据库课程设计报告

订 户 订 阅 报 刊 系 统

姓 名: 白璐 学 号: 3050603018 班 级:计算机0501 指导老师:

二○○八年一月

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

数据库课程设计

“数据库课程设计”是数据库系统及应用、软件工程及程序设计课程的后续实验课,是一门独立开设的实验课程。“数据库课程设计”可以进一步巩固学生的数据库知识,加强学生的实际动手能力和提高学生综合素质。

一、课程实验目的

1. 2. 3. 4.

加深对数据库系统、软件工程、程序设计语言的理论知识的理解和应用水平; 在理论和实验教学基础上进一步巩固已学基本理论及应用知识并加以综合提高; 学会将知识应用于实际的方法,提高分析和解决问题的能力,增强动手能力; 为毕业设计和以后工作打下必要基础。

二﹑课程实验题目

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。订单、订户、报刊目录、投递卡的数据见附表。

三、课程设计要求

运用数据库基本理论与应用知识,在微机RDBMS(SQL Server)的环境上建立一个数据库应用系统。要求把现实世界的事物及事物之间的复杂关系抽象为信息世界的实体及实体之间联系的信息模型,再转换为机器世界的数据模型和数据文件,并对数据文件实施检索、更新和控制等操作。

1. 用E-R图设计指定题目的信息模型; 2. 设计相应的关系模型,确定数据库结构; 3. 分析关系模式各属于第几范式,阐明理由; 4. 设计应用系统的系统结构图,确定系统功能;

5. 使用对象许可和命令许可、角色控制设计安全性控制检查程序;

6. 通过设计关系的主码约束、外码约束和使用CHECK、RULE实现完整性控制; 7. 为每一参照关系设计插入、删除、修改触发器; 8. 实现应用程序设计、编程、优化功能;

9. 对系统的各个应用程序进行集成和调试,进一步优化系统功能、改善系统用户界面

完成实验内容所指定的各项要求;

10. 分析遇到的问题,总结并写出课程设计报告; 11. 自我评价

四、课程设计考核

数据库课程采用课程设计报告和课程设计应用程序综合评定成绩。

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

五、实验环境

开发环境VC++、ODBC;数据库SQL Server

六、课程设计内容

(1) 创建数据库的结构 (2) 创建各基本表的结构 (3) 编制软件系统

完成数据的录入、修改和删除 按用户名称检索的订户信息

按用户名称检索订户订阅的报刊信息

七、课程设计过程

一. 课程设计任务

设计一个订户订阅报刊的应用系统。涉及订单、订户、报刊目录及投递卡信息。 1、系统语义描述如下:

一个订户可订多种报刊;一种报刊可被多个用户订阅;订单只能订阅现有报刊目录

内容;

一张投递卡可包含对多个订户的订单的投递信息; 2、系统功能包括:

订户管理:订户增加、修改、删除; 目录管理:目录增加、删除、修改; 订单管理:完成订户订阅数据的管理; 订单查询:按订户查询订单详细情况;

统计查询:按报刊目录统计各类报刊的订阅数量及金额 3、实现内容

创建数据库的结构 创建各基本表的结构

编制系统各功能模块,完成数据的管理(增、删、改)及统计查询。

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

二. 数据库系统设计 1.设计E-R图

2. 设计相应的关系模型,确定数据库结构

根据基础数据建立名为“报刊”的数据库,并建立三个关系表:订单表CUS_ORDER、

用户表CUSTOMER、报刊表NMTABLE,各表结构及数据结构如下:

(1)

CUS_ORDER表:

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

(2) CUSTOMER表:

(3)

报刊表NMTABLE:

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

3. 数据库范式分析

由于此数据库不存在传递依赖和部分依赖,所以该数据库系统属于第三范式。

4.设计应用系统的系统结构图,确定系统功能:

程序由MFC编写,编译平台为Microsoft Visual Studio .NET 2003。

流程图如下:

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

5.设计关系的主码约束、外码约束和使用CHECK实现完整性控制:

6. 应用程序编写 (1) 连结数据库

try {

HRESULT hr; // 创建Connection对象

hr = m_pConnection.CreateInstance("ADODB.Connection"); if( SUCCEEDED( hr ) )

{ // 连接数据库

hr=m_pConnection->Open("provider=SQLOLEDB.1;DataSource=127.0.0.1;userID=sa;Password=123456;Initial Catalog=报刊","","",adModeUnknown);

//MessageBox(0,_T("连结成功"),_T("成功"),0); } else

{MessageBox( NULL, "创建ADO对象失败", "失败", MB_OK ); return false; } }

catch( ... )

{ MessageBox( NULL,"连接数据库失败,请确定数据库是否启动且账号是否正确!", _T("连接数据库失败"), MB_OK); return false; }

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

程序采用COM接口连结数据库,所以先初始化OLE组件,再创建Connection实例,如果创建成功,就尝试连结,连结时用try catch捕捉数据库连结异常。如果发生异常,就提示用户数据连结出错。

(2) 订阅信息统计模块:

该模块将显示所有订阅信息,包括每个用户订了哪些报刊,报刊的份数,起至刊号及所订报刊的单价等所有数据信息,如图:

以下给出加载这些信息的函数。 _RecordsetPtr pRecord; try {

// 生成Recordset实例

pRecord.CreateInstance("ADODB.Recordset"); // 打开记录集,静态光标(静态记录集),乐观锁定方式 // 查询所有语句 sql="select

o,,customer.addr,cus_order.orderdate,NMTABLE.title,NMTABLE.price,NMTABLE.period,cus_order.start,cus_order.term,cus_order.qty from customer,cus_order,[NMTABLE] where o=cus_o and NMTABLE.nmno=cus_order.nmno";

pRecord->Open(_bstr_t(sql),_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);

while( !pRecord->adoEOF )

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

value = pRecord->GetCollect("cno"); if(value.vt!=VT_NULL) {

value.ChangeType(VT_BSTR); temp=value.bstrVal; } else

temp="";

m_list.InsertItem(i,temp);

value = pRecord->GetCollect("name"); if(value.vt!=VT_NULL) temp=value.bstrVal; else

temp="name";

m_list.SetItemText(i,1,temp.Trim()); value = pRecord->GetCollect("addr"); if(value.vt!=VT_NULL) temp=value.bstrVal; else

temp="";

m_list.SetItemText(i,2,temp.Trim()); value = pRecord->GetCollect("orderdate"); if(value.vt!=VT_NULL) {

value.ChangeType(VT_BSTR); temp=value.bstrVal; } else

temp="";

m_list.SetItemText(i,3,temp.Trim()); value = pRecord->GetCollect("title"); if(value.vt!=VT_NULL) temp=value.bstrVal; else

temp="";

m_list.SetItemText(i,4,temp.Trim()); value = pRecord->GetCollect("period"); if(value.vt!=VT_NULL)

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

else

temp="";

m_list.SetItemText(i,5,temp.Trim()); value = pRecord->GetCollect("start"); if(value.vt!=VT_NULL) {

value.ChangeType(VT_BSTR); temp=value.bstrVal; } else

temp="";

m_list.SetItemText(i,6,temp); value = pRecord->GetCollect("term"); if(value.vt!=VT_NULL) {

value.ChangeType(VT_BSTR); temp=value.bstrVal; } else

temp="";

m_list.SetItemText(i,7,temp); value = pRecord->GetCollect("qty"); if(value.vt!=VT_NULL) {

value.ChangeType(VT_BSTR); temp=value.bstrVal; } else

temp="";

m_list.SetItemText(i,8,temp); value = pRecord->GetCollect("price"); if(value.vt!=VT_NULL) {

value.ChangeType(VT_BSTR); temp=value.bstrVal; } else

temp="";

m_list.SetItemText(i,9,temp);

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

}

i++;

pRecord->MoveNext(); }

pRecord->Close(); pRecord = NULL; }

catch( _com_error *e ) {

MessageBox( e->ErrorMessage() );

}

首先,如同创建Connection实例,这里先创建一个Recordset实例,它相当于一个查询结果的元组指针;然后构造SQL语句,实现三表联合查询;再通过Recordset的Open方法执行SQL语句,使用Recordset保存查询的结果。最后,通过一个while循环,把Recordset中保存的结果全部读出,再将结果显示到列表框中,其中m_list是一个列表框的控制变量,先插入一行m_list.InsertItem(i,temp),i为列表框中现有的总项数,这样就可保证每次插入的数据是列表框的最后一项,由于已已经插入了一项,以后的就只要修改新插入项的数据即可m_list.SetItemText(i,9,temp)。

(3) 删除统计信息中的某一项:

在列表框的某一项上右击,将显示一个菜单,如图:

添加对应的消息处理函数,当选中删除菜单时,将删除列表框中被选中数据项。处理函数核心代码如下:

CString SQL;

_CommandPtr m_pCommand; int i;

i=m_list.GetSelectionMark();

SQL=(CString)"delete from [CUS_ORDER] where CNO=" + m_list.GetItemText(i,0);

SQL+=" and NMNO=(select NMNO from [NMTABLE] where title='" + m_list.GetItemText(i,4) + "')"; //MessageBox(SQL); try {

m_pCommand.CreateInstance("mand");

m_pCommand->ActiveConnection = theApp.m_pConnection; m_pCommand->CommandText = _bstr_t(SQL);

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

m_pCommand->Execute(NULL, NULL,adCmdText); //m_pCommand->Release(); }

catch(...) {

MessageBox("执行

SQL语句出错!"); }

首先用m_list.GetSelectionMark()得到当前被选中的列表项,然后生成SQL语句,完成后,创建Command实例,再设置它的各项参数,最后执行。

(4) 用户及报刊数据管理:

由于报刊数据和用户数据的管理类似,所以这里只对用户数据管理加以说明。

用户数据管理包括用户添加,用户信息修改,用户删除。如图:

以下分别对这三个功能模块加之分析说明。

数据添加:输入姓名和地址后选择添加,程序就会将此用户作为一个新用户增加到数据库中。添加按钮的消息处理函数如下:

CString SQL,temp;

_CommandPtr m_pCommand;

GetDlgItem(IDC_EDIT3)->GetWindowText(temp);// cno,name,addr from [CUSTOMER] SQL=(CString)"insert into [CUSTOMER](name,addr) values ('" + temp;

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

GetDlgItem(IDC_EDIT2)->GetWindowText(temp); SQL+="','"+temp+"')"; try {

m_pCommand.CreateInstance("mand");

m_pCommand->ActiveConnection = theApp.m_pConnection; m_pCommand->CommandText = _bstr_t(SQL); m_pCommand->Execute(NULL, NULL,adCmdText); //m_pCommand->Release(); }

catch(...) {

MessageBox("执行SQL语句出错!"); }

this->LoadUserData();

由于此函数和上面的右键菜单处理函数颇为相似,所以这里不加说明,后面的删除功能同理也不再叙述。

数据更新操作:当选择列表框中的任意一项时,处理列表框的LVN_ITEMCHANGED 消息,使下面的文本框中数据也自动更新。函数如下: void CFORMVIEW1::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult) {

for(i =0;i<m_list0.GetItemCount();i++ ) {

if(m_list0.GetItemState(i,LVIS_SELECTED)==LVIS_SELECTED)//选中LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 int i; CString temp;

状态。。

}

{ }

break;

temp=m_list0.GetItemText(i,1);

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

}

GetDlgItem(IDC_EDIT3)->SetWindowText(temp); temp=m_list0.GetItemText(i,2);

GetDlgItem(IDC_EDIT2)->SetWindowText(temp); *pResult = 0;

首先用一个循环得到被选中的数据项的编号,然后再根据编号得到被选中项

的用户姓名和地址。再用SetWindowText函数更新下面的文本框的数据。 当单击更新按钮时,完成数据的更新操作。先得到选中的数据项编号,再构造UPDATE语句,完成更新,由于更新操作也是使用Command

实例,所以这里也不再复述。

(5) 用户订报模块:

这是程序中最复杂的模块,它的功能是给指定的用户按要求订阅报刊,如图:

第一个列表框中显示的是系统中所有已登记的用户,左下方的列表中显示的是在用户列表框中选中的用户未订阅的报刊,右下方的列表中显示的就是此用户已订阅的报刊。为便于理解程序,先给出它的操作方法:假如要给用户“李宇”进行订报设置,就只要先在用户列表框中选中他,然后再在左下方的列表框中选择他要订阅的报刊(支持多选),填写好份数和起至刊号,最后只要单击“>>>>>”按钮即可完成订阅;同样假如他要取消订阅某刊物,就只要在右边的列表框中选中要取消的刊物名称,再单击“<<<<<”即可完成。以下分块来讲解各功能的程序实现。

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

(a) 由于选中用户列表框中某一用户,就要在下面的列表框中显示此用户未订的

报刊和此用户用户已订的报刊。这就要对用户列表框的LVN_ITEMCHANGED消息进行响应。首先定义一个LoadNMData函数,它有一个参数用户ID,用来为下面的列表框加载数据。函数代码如下: void CFORMVIEW2::LoadNMData(int s) {

_RecordsetPtr pRecord; _variant_t value; CString temp,sql; int i=0; // 清空list

m_list1.DeleteAllItems(); m_list2.DeleteAllItems(); try {

// 生成Recordset实例

pRecord.CreateInstance("ADODB.Recordset");

// 打开记录集,静态光标(静态记录集),乐观锁定方式 // 查询所有语句 未选报刊

sql=(CString)"select nmno,title,period,price from [NMTABLE] WHERE NMNO NOT IN (SELECT NMNO FROM [CUS_ORDER] WHERE CNO=0"+m_list0.GetItemText(s,0) +(CString)") ORDER BY NMNO";

pRecord->Open(_bstr_t(sql),_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);

while( !pRecord->adoEOF) {

value = pRecord->GetCollect("nmno"); if(value.vt!=VT_NULL) {

value.ChangeType(VT_BSTR); temp=value.bstrVal; } else

temp="";

m_list1.InsertItem(i,temp);

……

i++;

pRecord->MoveNext(); }

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

pRecord->Close();

// 查询所有语句 已选报刊

sql=(CString)"SELECT title,period,price,qty,start,term from [NMTABLE],[CUS_ORDER] WHERE NMTABLE.NMNO=CUS_ORDER.NMNO AND CNO=0"+ m_list0.GetItemText(s,0) +" ORDER BY NMTABLE.NMNO";

pRecord->Open(_bstr_t(sql),_variant_t((IDispatch*)theApp.m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText); i=0;

while( !pRecord->adoEOF) {

value = pRecord->GetCollect("title"); if(value.vt!=VT_NULL) temp=value.bstrVal; else

temp="";

m_list2.InsertItem(i,temp.Trim());

……

i++;

pRecord->MoveNext(); }

pRecord->Close(); pRecord = NULL;

//GetDlgItem(IDC_EDIT1)->SetWindowText(m_list2.GetItemText(s,3)); }

catch(...) {

MessageBox("载入数据出错!"); } }

先创建Recordset实例,再构造SQL语句,执行,限于篇幅关系,这里不再复述。 再说LVN_ITEMCHANGED消息处理函数,它先得到选中的用户列表项,再据次得到用户ID,再调用LoadNMData函数,完成报刊列表的更新。

(b) 用户订报功能的程序实现:当单击“>>>>>”按钮时先在CUS_ORDER表中

添加相应的用户订阅信息,调用LoadNMData对两列表数据进行更新。 函数代码如下:

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

void CFORMVIEW2::OnBnClickedButton1() {

CString SQL,temp; int i,j,k;

CString qty,start,term; _CommandPtr m_pCommand;

for(k=m_list0.GetItemCount()-1;k>=0;k--) {

if(m_list0.GetItemState(k,LVIS_SELECTED)==LVIS_SELECTED) break; }

j=m_list1.GetItemCount();

if(k<0 || j==0 || m_list1.GetSelectedCount()==0) {

MessageBox("请先选择你要订阅的报刊!"); return; }

GetDlgItem(IDC_EDIT1)->GetWindowText(qty); GetDlgItem(IDC_EDIT2)->GetWindowText(start); GetDlgItem(IDC_EDIT3)->GetWindowText(term); try {

m_pCommand.CreateInstance("mand");

m_pCommand->ActiveConnection = theApp.m_pConnection; for(i=0;i<j;i++) {

if(m_list1.GetItemState(i,LVIS_SELECTED)==LVIS_SELECTED) {

SQL=(CString)"INSERT INTO [CUS_ORDER](CNO,ORDERDATE,[NMNO],START,TERM,QTY)

VALUES(0"+m_list0.GetItemText(k,0)+(CString)",GetDate(),"

+m_list1.GetItemText(i,0)+","+start+","+term+","+qty +")"; m_pCommand->CommandText = _bstr_t(SQL);

m_pCommand->Execute(NULL, NULL,adCmdText);

} } }

catch(...) {

MessageBox("执行SQL语句出错!"); }

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

this->LoadNMData(k); }

程序中有一循环,for(i=0;i<j;i++) j为未订阅报刊列表中的总项数,每循环一次调用m_list1.GetItemState(i,LVIS_SELECTED)检查第i项有无被选中,若选中,则构造往CUS_ORDER表中添加数据的SQL语句并执行,这样就可使用用户一次订阅多份报刊,而不必重复选择,循环完成后调用LoadNMData进行列表框数据更新。

(c) 取消用户订阅功能的实现:在右边的列表框中选择要取消订阅的报刊,单

击“<<<<”按钮,完成取消操作,程序的实现和上面用户订报类似,只是把往数据库添加数据的SQL语句改成了把用户要取消订阅的数据从数据库删除的SQL语句,不再重复。

(6) 编译并执行:

编译时采用静态链结DLL库,可保证程序在各版本Windows平台上都能正常运行。执行结果如下:

(用户统计信息)

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

(报刊及用户数据管理)

(删除用户时的提示信息)

设计一个订户订阅报刊的应用系统。接收并且处理订户的订阅要求,回答订户的查询,统计报刊的订阅情况。

(用户订报及取消订报)

结束语

通过这次课程设计,使我对数据库系统的设计及应用有了更加深刻的认识,包括从E-R图的设计,数据结构定义到关系模型的设计,完整性约束的整个过程。

并且,通过本次课程设计,也使我的编程能力得到进一步提高,虽然以前也写过涉及数据库的MFC程序,但这次的程序编写要比以前更为系统化,使我对知识的掌握也更加全面。

通过这次课程设计,我了解了SQL数据库中的以前不大明白的技术运用。在SQL数据库中,我们把在数据库理论上的知识予以运用,如:建立视图,创建存储过程,应用事务等,在一些基本的数据库操作中,熟悉并巩固了SQL的语法知识。通过对课程设计要求的分析,我们也初步理解一个软件工程的开发流程及发展思路。培养了我们由书面文字要求到转化这种要求到现实模型的能力,即很大程度上培养了我们的建模能力,分析问题,总结归纳问题的能力。这次课程设计也不能说一帆风顺,其中遇到的一个个困难给了我们一次次重新学习,再次思索的机会。我们通过克服这一个个困难,让我们重新又对目前脑子里所掌握的知识进行审理,进行了再次的纠正或者完善,这些都是书本上学不来的。理论联系实际就在这里自然地得到实现。这对我们巩固已学知识,锻炼实践动手能力大有裨益。

本文来源:https://www.bwwdw.com/article/t5i1.html

Top