数据库接口实验1.docx
《数据库接口实验1.docx》由会员分享,可在线阅读,更多相关《数据库接口实验1.docx(17页珍藏版)》请在冰豆网上搜索。
数据库接口实验1
1.实验一数据库接口实验-1
1.1实验目的
1.通过实验了解通用数据库应用编程接口ODBC的基本原理和实现机制,熟悉主要的ODBC接口的语法和使用方法;
2.利用C语言(或其它支持ODBC接口的高级程序设计语言)编程实现简单的数据库应用程序,掌握基于ODBC的数据库访问的基本原理和方法
3.学习java语言,并采用jdbc接口方式对数据库进行访问
1.2实验内容
1.以教科书第四章关于SQL语言相关内容为基础,课后查阅、自学ODBC接口有关内容,包括ODBC的体系结构、工作原理、数据访问过程、主要API接口的语法和使用方法等。
2.以实验二建立的学生数据库为基础,编写C语言(或其它支持ODBC接口的高级程序设计语言)数据库应用程序,按照如下步骤访问数据库
(a)Step1.ODBC初始化,为ODBC分配环境句柄
(b)Step2.建立应用程序与ODBC数据源的连接
(c)Step3.利用SQLExecDirect语句,实现数据库应用程序对数据库的建立、查询、修改、删除等操作
(d)Step4.检索查询结果集
(e)Step5.结束数据库应用程序
1.3实验要求
1.要求所编写的数据库访问应用程序中使用到以下主要的ODBCAPI函数:
(1)SQLALLocEnv:
初始化ODBC环境,返回环境句柄
(2)SQLALLocConnect:
为连接句柄分配内存并返回连接句柄
(3)SQLConnect:
连接一个SQL数据资源
(4)SQLDriverConnect
连接一个SQL数据资源,允许驱动器向用户询问信息
(5)SQLALLocStmt
为语句句柄分配内存,并返回语句句柄
(6)SQLExecDirect
把SQL语句送到数据库服务器,请求执行由SQL语句定义的数据库访问
(7)SQLFetchAdvances
将游标移动到到查询结果集的下一行(或第一行)
(8)SQLGetData
按照游标指向的位置,从查询结果集的特定的一列取回数据
(9)SQLFreeStmt
释放与语句句柄相关的资源
(10)SQLDisconnect
切断连接
(11)SQLFreeConnect
释放与连接句柄相关的资源
(12)SQLFreeEnv
释放与环境句柄相关的资源
1.4实验环境
Mysql8.0版本数据库
VS2015c++编程环境
Window8操作系统
ODBC5.3版本数据库连接接口
1.5实验步骤——资源配置
1.5.1环境配置——ODBC下载
可以在官网下载odbc驱动,注意32位与64位区别,相关bug将在下面提到。
1.5.2环境配置——数据源配置
1.打开控制面板,找到管理工具
2.找到ODBC数据源,这里我用的是32位数据源。
(因为我之前用的是ODBC8.0版本64位的,在VS测试中连接失败,就换用了32位5.3版本)
3.在用户dsn中添加相应数据源,这里点击添加按钮
4.找到我们安装的ODBC相关驱动程序,我安装的是5.3版本,选择相应驱动
5.这里需要填写对应的要连接的数据库信息,DataSourseName任意命名都可以,TCPServer使用本地,User是数据库用户的名称(可以打开workbench找到),Password是用户对应密码,Database会自动检测出该用户建立的数据库,我们只需要进行相应选择。
6.填写好之后可以点击Test按钮测试是否可以成功连接。
如果不可以,就需要检查一下说数据库信息是否填写正确。
1.5.3环境配置——ODBC和MYSQL选择上面可能出现的bug
本次试验中这个问题困扰了我好久,起初我采用ODBC8.0和mysql8.0,由于都是64位,在VS中产生了DSN匹配错误,因此只能使用32位的低版本ODBC5.3。
但是在使用时发现ODBC5.3版本不能识别MYSQL8.0版本数据库,在添加数据源中检测不到数据库。
折腾了3个小时终于找到了问题所在,即8.0版本可之前版本的密码检测方式不同,因此在网上找到了相应的解决方法(修改数据库加密规则)。
在MYSQL命令行中执行下列语句:
ALTERUSER'root'@'localhost'IDENTIFIEDBY'password'PASSWORDEXPIRENEVER;#修改加密规则
ALTERUSER'root'@'localhost'IDENTIFIEDWITHmysql_native_passwordBY'password';#更新一下用户的密码
FLUSHPRIVILEGES;#刷新权限
再重置下密码:
alteruser'root'@'localhost'identifiedby'123qwe';
最终,终于使得5.3版本可以成功连接8.0的mysql数据库了。
1.5.4环境配置——VS属性设置
1.字符集设置,将字符集的Unicode变为多字符集
2.资源库导入
3.Lib文件包的导入
4.Libmysql.lib写入
1.6实验步骤——代码分析
1.6.1SC存储结构
structStu_Course
{
charsno[6];
charcno[4];
intgrade;
};
1.6.2实验语句
chartable_command[4][100]={"select*fromscwheresno='30201';",//查询
"INSERTINTO`sc`VALUE('30201','C01',80);",//插入
"updatescsetgrade=80wheresno='30201'andcno='C03';",//修改
"deletefromscwheresno='30201'&cno='C01';"};//删除
1.6.3初始化ODBC,获取ODBC环境句柄
HENVhEnv;
SQLRETURNrEturn;
//初始化ODBC环境,返回环境句柄
rEturn=:
:
SQLAllocEnv(&hEnv);
1.6.4与数据源ODBC建立连接
1.分配连接句柄
//分配连接句柄
rEturn=:
:
SQLAllocHandle(SQL_HANDLE_DBC,hEnv,&hDbc);
if(rEturn==SQL_SUCCESS)
cout<<"连接句柄分配成功!
"<else{
cout<<"连接句柄分配失败!
"<return-1;
}
2.连接数据源
//连接数据源
rEturn=:
:
SQLConnect(hDbc,(SQLCHAR*)Dsn,SQL_NTS,(SQLCHAR*)userId,SQL_NTS,(SQLCHAR*)userPw,SQL_NTS);
if(rEturn==SQL_SUCCESS)
cout<<"数据源连接成功!
"<else{
cout<<"数据源连接失败!
"<return-1;
}
1.6.5释放连接资源
在应用程序完成数据库操作,退出运行之前,必须释放程序中使用的系统资源。
这些系统资源包括:
语句句柄、连接句柄和ODBC环境句柄。
完成这个过程的步骤如下:
1.调用SQLFreeStmt函数释放语句句柄及其相关的系统资源。
SQLFreeStmt(hstmt,SQL_DROP);//释放与语句句柄相关的资源
2.调用SQLFreeConnect函数释放连接句柄及其相关的系统资源。
SQLFreeConnect(hdbc);//释放与连接句柄相关的资源
3.调用SQLFreeEnv函数释放环境句柄及其相关的系统资源,停止ODBC操作。
SQLFreeEnv(env);//释放与环境句柄相关的资源
1.7实验步骤——结果分析
1.7.1执行查询操作
Mysql代码:
select*fromscwheresno='30201';
功能:
查询SC表中学号为30201的学生的选课情况
1.7.2
Mysql代码:
INSERTINTO`sc`VALUE('30201','C01',80);
功能:
在学号为30201的学生的选课中添加课程号为C01的课程,并令其成绩为80分。
1.7.3
Mysql代码:
updatescsetgrade=80wheresno='30201'andcno='C03';
功能:
将学号为30201学号的学生的课程号为C03的选课成绩改为80分。
1.7.4
Mysql代码:
deletefromscwheresno='30201'andcno='C01';
功能:
将学号为30201的学生的课程号为C01的选课删除。
1.8实验源代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
//定义ODBC连接的数据源信息
#defineDSN"rxk.test"
#defineID"root"
#definePS"ru072312"
//命令mysql代码
chartable_command[4][100]={"select*fromscwheresno='30201';",//查询
"INSERTINTO`sc`VALUE('30201','C01',80);",//插入
"updatescsetgrade=80wheresno='30201'andcno='C03';",//修改
"deletefromscwheresno='30201'andcno='C01';"};//删除
//SC存储结构
structStu_Course{
charsno[6];
charcno[4];
intgrade;
};
voidquery_table(SQLHDBChDbc);//查询表
voidinsert_table(SQLHDBChDbc);//插入表
voidmodify_table(SQLHDBChDbc);//修改表项
voiddelete_table(SQLHDBChDbc);//删除表项
intmain(void)
{
charDsn[10]=DSN,userId[5]=ID,userPw[13]=PS;//连接信息
HENVhEnv;
SQLHDBChDbc;
SQLRETURNrEturn;
//初始化ODBC环境,返回环境句柄
rEturn=:
:
SQLAllocEnv(&hEnv);
if(rEturn==SQL_SUCCESS)
cout<<"环境句柄创建成功!
"<else{
cout<<"环境句柄创建失败!
"<return-1;
}
//分配连接句柄
rEturn=:
:
SQLAllocHandle(SQL_HANDLE_DBC,hEnv,&hDbc);
if(rEturn==SQL_SUCCESS)
cout<<"连接句柄分配成功!
"<else{
cout<<"连接句柄分配失败!
"<return-1;
}
//连接数据源
rEturn=:
:
SQLConnect(hDbc,(SQLCHAR*)Dsn,SQL_NTS,(SQLCHAR*)userId,SQL_NTS,(SQLCHAR*)userPw,SQL_NTS);
if(rEturn==SQL_SUCCESS)
cout<<"数据源连接成功!
"<else{
cout<<"数据源连接失败!
"<return-1;
}
intop=0;//选择操作类型
boolflag=true;//判断是否退出
while(flag){
cout<<"**************************请选择服务项目****************************"<cout<<"1.查询sc数据库2.插入数据库3.修改数据库4.删除数据5.退出"<cin>>op;
switch(op){
case1:
cout<<"查询sc数据库"<query_table(hDbc);
break;
case2:
cout<<"插入数据库"<insert_table(hDbc);
query_table(hDbc);
break;
case3:
cout<<"修改数据库"<modify_table(hDbc);
query_table(hDbc);
case4:
cout<<"删除数据"<delete_table(hDbc);
query_table(hDbc);
break;
case5:
cout<<"退出"<flag=false;
break;
default:
cout<<"无效命令"<break;
}
}
if(SQLFreeConnect(hDbc)==SQL_SUCCESS)
cout<<"释放连接句柄资源成功!
"<if(SQLFreeEnv(hEnv)==SQL_SUCCESS)
cout<<"释放环境句柄资源成功!
"<return0;
}
voidquery_table(SQLHDBChDbc)
{
structStu_Course*aSC=(Stu_Course*)malloc(sizeof(Stu_Course));
HSTMThstmt;
RETCODEretcode;
SQLLENlen1,len2,len3;
retcode=SQLAllocStmt(hDbc,&hstmt);//语句句柄分配
if(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO){//语句句柄分配成功
//建立缓冲的连接
SQLBindCol(hstmt,1,SQL_C_CHAR,aSC->sno,6,&len1);
SQLBindCol(hstmt,2,SQL_C_CHAR,aSC->cno,4,&len2);
SQLBindCol(hstmt,3,SQL_C_SLONG,&aSC->grade,3,&len3);
retcode=SQLExecDirect(hstmt,(SQLCHAR*)table_command[0],SQL_NTS);//查询操作执行
if(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO){
cout<<"学号课程名成绩"<retcode=SQLFetch(hstmt);//依次取出缓冲区的内容
while(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO){
cout<sno<<""<cno<<""<grade<retcode=SQLFetch(hstmt);
}
}
elsecout<<"选择语句执行失败"<}
elsecout<<"句柄内存分配失败"<//释放资源
SQLFreeStmt(hstmt,SQL_DROP);
free(aSC);
}
voidinsert_table(SQLHDBChDbc)
{
HSTMThstmt;
RETCODEretcode;
retcode=SQLAllocStmt(hDbc,&hstmt);//语句句柄分配
if(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO){
//执行mysql插入操作
retcode=SQLExecDirect(hstmt,(SQLCHAR*)table_command[1],SQL_NTS);
if(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO)
cout<<"执行插入语句成功"<else
cout<<"插入语句执行失败"<}
elsecout<<"句柄内存分配失败"<//释放资源
SQLFreeStmt(hstmt,SQL_DROP);
}
voidmodify_table(SQLHDBChDbc)
{
HSTMThstmt;
RETCODEretcode;
retcode=SQLAllocStmt(hDbc,&hstmt);//语句句柄分配
if(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO){
//执行mysql修改操作
retcode=SQLExecDirect(hstmt,(SQLCHAR*)table_command[2],SQL_NTS);
if(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO)
cout<<"修改语句执行成功"<else
cout<<"修改语句执行失败"<}
elsecout<<"句柄内存分配失败"<//释放资源
SQLFreeStmt(hstmt,SQL_DROP);
}
voiddelete_table(SQLHDBChDbc)
{
HSTMThstmt;
RETCODEretcode;
retcode=SQLAllocStmt(hDbc,&hstmt);//语句句柄分配
if(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO){
//执行mysql删除操作
retcode=SQLExecDirect(hstmt,(SQLCHAR*)table_command[3],SQL_NTS);
if(retcode==SQL_SUCCESS||retcode==SQL_SUCCESS_WITH_INFO)
cout<<"删除语句执行成功"<else
cout<<"删除语句执行失败"<}
elsecout<<"句柄内存分配失败"<//释放资源
SQLFreeStmt(hstmt,SQL_DROP);
}
1.9实验总结
本次实验在配置环境的时候让我更进一步的了解到了数据库的一些内部情况,和内部命令的使用,例如更改加密规则、更新权限、重置密码等。
同时也让我对32位和64位的区别有了一定的了解,同时也有了一定的谨慎,一旦出错很难被发现。
本次实验过程:
首先创建了ODBC数据源,与数据库进行连接,然后进行代码编写:
1.初始化ODBC,获取ODBC环境句柄
2.与ODBC数据源建立连接
3.通过连接向ODBC数据库提交SQL语句,实现存取数据 4.结束应用程序,释放连接 需要提交的SQL语句实现存放在数组中,在第三步通过语句句柄提交执行,也可以仅分配内存空间,输入sql语句,再执行。
通过这次实验,我了解了数据库应用编程接口ODBC的基本原理和实现机制,并对MySQL中的ODBC的使用和ODBC接口的语法和函数等有了进一步的了解。
还通过在VS中编写C语言程序实现简单的数据库应用程序,较好地掌握基于ODBC的数据库访问的基本原理和方法,在实践中较好的掌握ODBC相关知识。