数据库实验报告.docx
《数据库实验报告.docx》由会员分享,可在线阅读,更多相关《数据库实验报告.docx(25页珍藏版)》请在冰豆网上搜索。
数据库实验报告
地理与生物信息学院
2012/2013学年第一学期
实验报告
课程名称:
数据库
实验名称:
嵌入式SQL、存储过程及ODBC等访问数据库
班级学号
学生姓名周炳威,
指导教师
日期:
2013年5月
一、实验题目及实验环境:
嵌入式SQL、存储过程及ODBC等访问数据库
操作系统:
Windows7
数据库管理系统:
SQLSERVER2000个人版
Compiler:
VisualC++6.0
2、实验内容:
1.通过C语言编写访问数据库的应用程序来对数据库进行操作
嵌入式SQL、ODBC
2.用SQLServer编写存储过程,对数据库进行操作
3.通过嵌入式SQL,对学生课程数据库中的表,完成下面功能:
4.依次检查某个系的学生记录,交互式更新学生年龄。
5.对学生课程数据库,编写存储过程,完成下面功能:
6.统计某一门课程的成绩分布情况,即按照各分数段统计人数。
7.使用ODBC编写应用程序,对学生课程数据库中的表,完成下面功能:
8.查询选修某一门课程的选课信息,要查询的课程号由用户在程序运行过程中指定,放在主变量中
3、实验过程及完成情况:
建立数据库表:
1.嵌入式sql
嵌入式SQL的C语言应用程序在VC++6.0、SQLServer2000环境下的调试可分为五步:
第一步环境初始化;
第二步预编译;
第三步编译;
第四步连接;
第五步运行。
1、环境初始化
(1)将文件夹devtools复制到SQLServer的系统目录C:
\ProgramFiles\MicrosoftSQLServer\(或在安装MicrosoftSQLServer2000时选择安装DevelopmentTools,为使用嵌入式SQL语言准备必要的头文件和库文件。
)
(2)初始化VisualC++6.0编译器环境。
在命令行方式下运行文件\MicrosoftVisualStudio\VC98\Bin\vcvars32.bat。
运行文件\MicrosoftVisualStudio\VC98\Bin\vcvars32.bat。
(3)初始化SQLServer的预编译环境。
在命令行方式下运行文件:
C:
\ProgramFiles\MicrosoftSQLServer\DEVTOOLS\SAMPLES\ESQLC\setenv.bat。
直接是由附件里的运行程序直接运行
(4)VC++6.0环境配置。
具体配置分为如下三步:
①单击菜单中Tools(工具)->options(选择)->directories(目录)->IncludeFiles:
添加C:
\ProgramFiles\MicrosoftSQLServer\devtools\include。
将SQLserver自带的用于数据库开发的头文件包含到工程环境中。
②Tools(工具)->options(选择)->directories(目录)->LibFiles:
添加C:
\ProgramFiles\MicrosoftSQLServer\devtools\x861ib。
将开发用到的包包含到工程中。
③project(工程)->Settings(设置)->Link->Object(对象)/LibraryModules(库模块),添加库文件:
SQLakw32.lib,Caw32.lib。
这两个文件之间用空格分开。
注意:
在VC++6.0中要先创建一个"WIN32ConsoleApplication"的Proiect,才可以做该设置。
2、预编译
1)复制ESQL预编译文件及库文件
C语言编译程序不能识别应用程序中的SQL语句,需要经过预处理程序将其转换成C语句。
SQLServer的预处理程序是nsqlprep.exe。
nsqlprep.exe在SQLServer安装日录的MSSQL\Binn下。
若SQLServer数据库采用的是默任安装方式,则需要把nsqlprep.exe、SQLAIW32.DLL、SQLAKW32.DLL三个文件拷贝到MSSQL\Binn目录下。
2)将动态链接库SQLAKW32.dll,SQLAIW32.dll文件拷贝到操作系统目录下的子目录C:
\WINDOWS\system32中。
预编译nsqlprep.exe配置生成:
tess.c
3)tess.c加入工程Esql
创建嵌入式SQL的C源文件Esql.c
ess.sqc文件
#include
voidmain()
{
EXECSQLBEGINDECLARESECTION;
charfirst_name[40];
charlast_name[]="White";
EXECSQLENDDECLARESECTION;
EXECSQLCONNECTTOSONGYNTAO-PC.pubsUSERsa.since1992;
EXECSQLSELECTau_fnameINTO:
first_namefromauthorsWHEREau_lname=:
last_name;
EXECSQLDISCONNECTALL;
printf("firstname:
%s\n",first_name);
}
4)编译,连接与运行
在VC++6.0中创建一个"WIN32ConsoleApplication"的Proiect,然后将预编译生成的c文件加入Proiect,编译连接即可生成访问SQLServer的可执行程序。
3.出现的问题:
实验上机前,因为个人电脑安装C++在D盘,所以实验初始化VisualC++6.0编译器环境以及初始化SQLServer的预编译环境时,利用附件里的运行程序直接浏览编译再运行文件。
在联系到数据库时需要建立一个数据库名首字母不为数字的标示符,以便运行。
在实验上机时不能运用附件的运行程序运行文件。
故所有的运行程序必须在在命令行方式下运行。
编写程序:
#include
#include
EXECSQLBEGINDECLARESECTION;/*主变量说明开始*/
chardeptname[22];
charHSno[10];
charHSname[22];
charHSsex[4];
intHSage;
intNEWAGE;
longSQLCODE;
EXECSQLENDDECLARESECTION;
EXECSQLINCLUDEsqlca;
/*************************************************************************/
intmain(void)
{
intcount=0;
charyn;
printf("Pleasechoosethedepartmentname(CS/MA/IS):
");
scanf("%s",deptname);
EXECSQLCONNECTTOStudent;
EXECSQLDECLARESXCURSORFOR
SELECTSno,Sname,Ssex,Sage
FROMStudent
WHERESDept=:
deptname;
EXECSQLOPENSX;
for(;;){
EXECSQLFETCHSXINTO:
HSno,:
HSname,:
HSsex,:
HSage;
if(sqlca->sqlcode!
=0)
{printf("数据处理结束!
");
break;
if(count++==0)
printf("\n%-10s%-22s%-4s%-10s\n","Sno","Sname","Ssex","Sage");
printf("%-10s%-22s%-4s%-10d\n",HSno,HSname,HSsex,HSage);
printf("UPDATEAGE(y/n)?
");/*询问用户是否要更新该学生的年龄*/
do{
scanf("%c",&yn);
}
while(yn!
='N'&&yn!
='n'&&yn!
='Y'&&yn!
='y');
if(yn=='y'||yn=='Y')/*如果选择更新操作*/
{
printf("INPUTNEWAGE:
");
scanf("%d",&NEWAGE);/*用户输入新年龄到主变量中*/
EXECSQLUPDATEStudent/*嵌入式SQL*/
SETSage=:
NEWAGE
WHERECURRENTOFSX;
}/*对当前游标指向的学生年龄进行更新*/
}
EXECSQLCLOSESX;/*关闭游标SX不再和查询结果对应*/
EXECSQLCOMMITWORK;/*提交更新*/
EXECSQLDISCONNECTTEST;/*断开数据库连接*/
}
4.解决方案(列出遇到的问题和解决办法,列出没有解决的问题):
实验如下所示:
运行结果如下所示:
2存储过程:
实验内容与完成情况:
新建存储过程:
CREATEPROCEDURECount_r
(@HCnamechar(40))
as
selectCount(sno)as优秀人数
fromcourse,stc
whereo=oandcname=@HCnameandscorebetween90and100;
selectCount(sno)as良好人数
fromcourse,stc
whereo=oandcname=@HCnameandscorebetween80and90;
selectCount(sno)as一般人数
fromcourse,stc
whereo=oandcname=@HCnameandscorebetween70and80;
selectCount(sno)as及格人数
fromcourse,stc
whereo=oandcname=@HCnameandscorebetween60and70;
selectCount(sno)as不及格人数
fromcourse,stc
whereo=oandcname=@HCnameandscorebetween0and60;
GO
execCount_r
@HCname='java';
2.出现的问题
在新建存储过程中如果在执行之后再修改存储过程,数据库会提示存储过程xxx已经存在,无法完成修改,并且会在查询中报错。
3.解决的办法:
执行指令dropprocXXX;将存储过程删除后重新输入。
就能正常解决,实现上述的的查询结果。
3.ODBC链接数据库:
实验内容与完成情况
1、配置ODBC,为SQLServer添加数据源
2.ODBC应用程序流程
a.初始化阶段
分配环境句柄
分配连接句柄
在分配连接句柄前,最好先设置环境句柄所用的ODBC参数
b.建立连接
分配语句句柄
程序主体
c.结束部分
释放语句句柄
断开数据源连接
释放连接句柄
释放环境句柄
二:
编写程序查询stc的数据
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
charhosts[]={"127.0.0.1"};
#defineisSuc(result)((result)==SQL_SUCCESS||(result)==SQL_SUCCESS_WITH_INFO)
intmain(void)
{
shortsret;//返回代码
HENVhenv;//环境句柄
HDBChdbc;//连接句柄
HSTMThstmt;//sql语句执行句柄,相当于游标
//动态创建系统DSN数据源,需要包含odbcinst.h,SQLServer不需要添加用户名密码
//在使用某个数据库的ODBC管理器之前,首先要查看是否安装了这个数据库的ODBC驱动,如果没有先安装再使用,比如DB2就没有默认安装
//SQLConfigDataSource(NULL,ODBC_ADD_SYS_DSN,"SQLServer","DSN=trantest\0UID=sa\0PWD=123456\0SERVER=192.168.100.54\0DATABASE=warehouse\0");
boolsucess=SQLConfigDataSource(NULL,ODBC_ADD_SYS_DSN,"SQLServer","DSN=stu\0SERVER=127.0.0.1\0DATABASE=stu\0");
if(sucess)
printf("DSNcreatedsucessfully!
!
\n");
else
exit(0);
/**申请环境句柄**/
sret=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
if(!
isSuc(sret))
{
printf("申请环境句柄出错\n");
SQLFreeHandle(SQL_HANDLE_ENV,henv);
}
/**设置环境属性,注册ODBC版本**/
sret=SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(void*)SQL_OV_ODBC3,0);
if(!
isSuc(sret))
{
printf("注册ODBC版本出错\n");
}
/**申请连接句柄**/
sret=SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
if(!
isSuc(sret))
{
printf("申请连接句柄出错\n");
SQLFreeHandle(SQL_HANDLE_DBC,hdbc);
}
/**设置连接属性,此处设置为手动提交**/
sret=SQLSetConnectAttr(hdbc,SQL_ATTR_AUTOCOMMIT,(void*)SQL_AUTOCOMMIT_OFF,SQL_IS_POINTER);
if(!
isSuc(sret))printf("设置连接属性出错\n");
/**连接数据源,这里的数据源使用的是动态创建的数据源**/
sret=SQLConnect(hdbc,(SQLCHAR*)"stu",SQL_NTS,(SQLCHAR*)"sa",SQL_NTS,(SQLCHAR*)"zhoubingwei",SQL_NTS);
if(!
isSuc(sret))printf("连接%s出错\n",hosts);
elseprintf("连接%s成功\n",hosts);
/**申请执行语句句柄**/
sret=SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt);
if(!
isSuc(sret))
{
printf("申请执行语句句柄时出错\n");
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
}
//记录更新语句影响的行数
SQLINTEGERrow_count;
SQLExecDirect(hstmt,(SQLCHAR*)"insertintoodbctestvalues(100,'name','2011-11-30')",SQL_NTS);
//执行sql语句后影响的行数,select查询语句返回-1
SQLRowCount(hstmt,&row_count);
printf("affctedcountis:
%d\n",row_count);
SQLExecDirect(hstmt,(SQLCHAR*)"insertintoodbctestvalues(200,'name','2011-11-30')",SQL_NTS);
SQLRowCount(hstmt,&row_count);
printf("affctedcountis:
%d\n",row_count);
SQLExecDirect(hstmt,(SQLCHAR*)"deletefromodbctestwherea=200",SQL_NTS);
SQLRowCount(hstmt,&row_count);
printf("affctedcountis:
%d\n",row_count);
//对更新类的sql执行后进行提交或者回滚
sret=SQLEndTran(SQL_HANDLE_DBC,hdbc,SQL_COMMIT);
//sret=SQLEndTran(SQL_HANDLE_DBC,hdbc,SQL_ROLLBACK);
if(sret!
=SQL_SUCCESS)
printf("服务器%s执行查询出错\n",hosts);
else
printf("服务器%s执行查询成功\n",hosts);
SQLExecDirect(hstmt,(SQLCHAR*)"select*fromodbctest",SQL_NTS);
intset_num=0;
SQLINTEGERID;
SQLSMALLINTcol_num;
SQLCHARszId[50],szName[50],szTime[50];
SQLINTEGERcbID,cbName,cbTime;
//得到结果集中列数
SQLNumResultCols(hstmt,&col_num);
printf("columnnumberis:
%d\n",col_num);
//要遍历所有的结果集可以利用下面的方法:
while(SQL_NO_DATA!
=SQLFetch(hstmt))//移动光标,一直到集合末尾
{
//得到光标处某列的值
SQLGetData(hstmt,1,SQL_C_ULONG,&ID,0,&cbID);
SQLGetData(hstmt,2,SQL_C_CHAR,szName,50,&cbName);
SQLGetData(hstmt,3,SQL_C_CHAR,szTime,50,&cbTime);
//有与ODBC没有MoveNext和MoveLastAPI所以这样获取数据集行数
set_num++;
printf("%d,%s,%s\n",ID,szName,szTime);
}
printf("thenumbersofsetis:
%d\n",set_num);
/**释放各个句柄,注意顺序,不要改变**/
SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC,hdbc);
SQLFreeHandle(SQL_HANDLE_ENV,henv);
return0;
}
实验问题:
只能连接数据库,无法正确显示查询信息
解决方案:
采用MFC连接数据库:
建立MFC工程,添加数据库
建立成功后,制作显示界面
(1)创建一个对话框,并添加控件,如图9-18所示。
设置编辑框的ID为IDC_FILTER.。
为该对话对话框添加一个新的对话框类CFilterDlg并使用ClassWizard为编辑框IDC_FILTER在对话框类CFilterDlg中添加一个Ctring类型的成员变量m_Filter。
图9-18查询对话框
(2)在“查看”菜单下添加一个新的菜单项“筛选”,菜单项ID设为ID_VIEW_FLITER,使用ClassWizard在CExam9_1View类中为菜单项ID_VIEW_FILTER映射菜单处理函数,得到函数OnViewFilter()。
(3)在CExam9_1View类的实现文件中使用include命令包含“FilterDlg.h”文件,并在函数OnViewFilter()中添加代码,调用筛选对话框,并按对话框返回的字符串设置数据成员m_strFilter的值,实现筛选。
若对话框返回空串,显示整个记录集。
如图
编写查询函数:
voidCOdbcView:
:
OnViewFliter()
{
//TODO:
Addyourcommandhandlercodehere
CFilterDlgdlg;
CStringstr;
if(dlg.DoModal()==IDOK)//调用筛选对话框,按OK按钮返回
{if(dlg.m_Filter.IsEmpty())//编辑框为空,显示整个记录集
str="";
else
str="cno='"+dlg.m_Filter+"'";//定义筛选字符串
m_pSet->m_strFilter=str;
m_pSet->Requery();//重新查询记录集
UpdateData(false);//更新控件显示
}
}
实验结果:
实验运行时,可以点击窗口的图标查看下一条记录。
如输入为空时,返回原来一条结果集。
图1:
运行时,显示