北京邮电大学
实验报告
课程名称 数据库系统原理
实验内容 实验四
实验名称 数据库接口实验
班级 姓名
指导老师
成绩_________
2018 年 10 月 30 日
实验四 数据库接口实验
实验目的:
1.通过实验了解通用数据库应用编程接口 ODBC 的基本原理和实现机制,熟悉主要的 ODBC
接口的语法和使用方法;
2.利用 C 语言(或其它支持 ODBC 接口的高级程序设计语言)编程实现简单的数据库应用程
序,掌握基于 ODBC 的数据库访问的基本原理和方法。
3.尝试使用 SQL Server 上的工具以特定格式导出数据,初步了解现代程序设计辅助工具的
使用,加深对接口和数据库与外界的联系的认识。
实验内容:
本实验内容主要是如何通过数据库接口访问(包括增、删、改)数据库中的数据。
要求能够通过编写程序或者使用 SQL Server 工具访问到数据。该实验的重点在于 ODBC
数据源配置和工具使用,而不在于编写有一定复杂度的程序。
实验环境
C/S 结构,SQL Server 企业版服务器及客户端。
数据库存储在服务器上,表和视图定义也存储在服务器上,但同学通过网络使用客户端
连接到服务器上进行操作。
实验步骤
(a) 以实验二建立的数据库为基础,编写 C 语言(或其它支持 ODBC 接口的高级程序
设计语言) 数据库应用程序,按照如下步骤访问数据库
i.
ii.
iii.
Step1. ODBC 初始化,为 ODBC 分配环境句柄
Step2. 建立应用程序与 ODBC 数据源的连接
Step3. 利用 SQLExecDirect 语句,实现数据库应用程序对数据库中表(有数
据)进行数据查询、修改、删除、插入等操作。要求先打印出所有记录,然后
插入一行,再打印一次,进行修改,再打印一次,最后删除一行,再打印一次。
iv.
Step4. 结束数据库应用程序
源程序代码:
#include
#include
#include
#include
#include
#include
#include
SQLRETURN retcode; //结果返回
SQLHENV env;
//环境句柄
SQLHDBC conn;
//数据库连接句柄
SQLHSTMT stmt;
//语句句柄
void F(SQLCHAR s[],int flag,int colNum)
{
printf("-------------------------------\n\n%s\n",s);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
//执行 SQL 指令
retcode = SQLExecDirect(stmt, s, SQL_NTS);
if ((retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) && flag==1)
{
char ss[10][40]; SQLINTEGER len[10];
while (TRUE)
{
retcode = SQLFetch(stmt);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
int i;
for (i = 1; i <= colNum; i++) {
SQLGetData(stmt, i, SQL_C_CHAR, ss[i], sizeof(ss[i]),
&len[i]);
printf("%-15s\t", ss[i]);
}
printf("\n");
}
else break;
}
}
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
//SQLFreeStmt(stmt, SQL_DROP); 两者等价
}
}
int main()
{
//分配环境句柄
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
//With some drivers you might set the cursor type, prepare a statement and then
execute it. When SQLExecute is called the statement is acted upon but the driver might change
the cursor type to something else.
//In this case, SQLExecute would return SQL_SUCCESS_WITH_INFO and the driver would
add a diagnostic indicating the cursor type had been changed
//If you ask for ODBC 3 behavior and the driver does not support ODBC 3, the driver
manager will return SQL_SUCCESS_WITH_INFO from SQLDriverConnect and a state of HYC00 (The
driver does not support the version of ODBC behavior that the application requested);
//设置环境属性
retcode = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
//设置登陆超时时间为 5s
SQLSetConnectAttr(conn, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
//连接(2) SQLDriverConnect:直接连 SQLConnect:需要设置 odbc 数据源
//retcode = SQLDriverConnect(conn, NULL, (SQLCHAR*)"DRIVER={SQL
Server};SERVER=USER-20180618HV;DATABASE=curricula-variable;UID=sa;PWD=sqlseverzzp123;",
SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
retcode = SQLConnect(conn, (SQLCHAR*)"test2", SQL_NTS, (SQLCHAR*)"sa",
SQL_NTS, (SQLCHAR*)"sqlseverzzp123", SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
printf("Connected!!!!\n");
SQLCHAR sql[4][100] = {
"select * from student","insert into student values('g95566',
'zzp', '男', '1998-05-29','666','shanxi')",
'zzp'","delete from student where student_name = 'zzp'"
"update student set class_id = '111' where student_name =
};
F(sql[0], 1, 6); F(sql[1], 0, 6);
F(sql[0], 1, 6); F(sql[2], 0, 6);
F(sql[0], 1, 6); F(sql[3], 0, 6);
F(sql[0], 1, 6);
}
else printf("error!");
SQLDisconnect(conn);
SQLFreeHandle(SQL_HANDLE_DBC, conn);
//SQLFreeConnect(conn);两者等价
}
}
SQLFreeHandle(SQL_HANDLE_ENV, env);
//SQLFreeEnv(env); 两者等价
}
system("pause");
return 0;
}
运行结果截图
代码解读
1. 概要
首先我们要分配环境句柄 SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env),
SQLAllocHandle 是句柄分配函数,第一个参数 SQL_HANDLE_ENV 表明是环境句柄,第二个参数
是 inputHadle,由于是环境句柄,故为 SQL_NULL_HANDLE。第三个参数是*outputHandle,输
出到我们提前定义好的环境句柄全局变量 env 中。
然后设置环境属性 SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3,
0),这几个参数是指明 odbc 版本。
之后分配数据连接句柄 SQLAllocHandle(SQL_HANDLE_DBC, env, &conn),表明分配的是数
据连接句柄,inputHandle 是之前设置好的环境 env,*outputHandle 是&conn,输出到我们
提前定义好的数据库连接句柄 conn 中。
接下来设置登陆超时时间为 5s:SQLSetConnectAttr(conn, SQL_LOGIN_TIMEOUT,
(SQLPOINTER)5, 0)。
接下来连接 odbc 数据源(之后会介绍如何设置 odbc 以及不用连接 odbc 如何直接连数
据库),SQLConnect(conn, (SQLCHAR*)"test2", SQL_NTS, (SQLCHAR*)"sa", SQL_NTS,
(SQLCHAR*)"sqlseverzzp123", SQL_NTS),第一个参数是数据库连接句柄,之后几个参数是 dns、
ID、Psd。SQL_NTS 意思是上个参数的长度。
之后我们要执行 SQL 语句。在自己定义的 F(SQLCHAR s[],int flag,int colNum)函数里,
第一个参数是 SQL 语句内容,flag 为 1 时表示要输出,colNum 表示输出多少列。先分配语
句句柄 SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt),然后执行语句 SQLExecDirect(stmt, s,
SQL_NTS),如若要输出的话用 SQLFetch(stmt)获取下一行,用 SQLGetData(stmt, i, SQL_C_CHAR,
ss[i], sizeof(ss[i]), &len[i])来获取第 i 列数据并绑定到某个字符串中,len[i]存储数据
长度(也可以使用 SQLBindCol 函数来绑定列,之后用 SQLFetch 不断获取下一行来输出)。
然后 free 语句句柄用 SQLFreeHandle(SQL_HANDLE_STMT, stmt)来实现。
最后用 SQLDisconnect(conn)来断开数据库连接,用 SQLFreeHandle(SQL_HANDLE_DBC, conn)
来 free 连接句柄,用 SQLFreeHandle(SQL_HANDLE_ENV, conn)来 free 环境句柄。
2. 说明
1)很多函数都是 SQLRETURN 返回类型,当值为 SQL_SUCCESS||SQL_SUCCESS_WITH_INFO 说明
执行成功,为何会有 SQL_SUCCESS_WITH_INFO 代码里有说明:With some drivers you might set
the cursor type, prepare a statement and then execute it. When SQLExecute is called the
statement is acted upon but the driver might change the cursor type to something else.In
this case, SQLExecute would return SQL_SUCCESS_WITH_INFO and the driver would add a
diagnostic indicating the cursor type had been changed.If you ask for ODBC 3 behavior and
the driver does not support ODBC 3, the driver manager will return SQL_SUCCESS_WITH_INFO
from SQLDriverConnect and a state of HYC00 (The driver does not support the version of ODBC
behavior that the application requested).
2)SQLFreeHandle(SQL_HANDLE_ENV, env)与 SQLFreeEnv(env)是等价的,
SQLFreeHandle(SQL_HANDLE_DBC, conn)与 SQLFreeConnect(conn)是等价的,
SQLFreeHandle(SQL_HANDLE_STMT, stmt)与 SQLFreeStmt(stmt, SQL_DROP)是等价的。
3)通过 SQLDriverConnect(conn, NULL, (SQLCHAR*)"DRIVER={SQL
Server};SERVER=USER-20180618HV;DATABASE=curricula-variable;UID=sa;PWD=sqlseverzzp123;",
SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE)可以直接连数据库。
(b)在 Windows 控制面板中通过管理工具下的 ODBC 数据源工具在客户端新建连接到
SQL Server 服务器的 ODBC 数据源,测试通过后保存,注意名字要和应用程序中引用的数
据源一样。
打开控制面板,搜索 odbc
点击设置 odbc 数据源 32 位,选择系统 DSN,点击添加(下图中有我已经添加好的)