1、第十二章 SQL中的数据交换之调用层接口方式,12.1 调用层接口概述 12.2 C/S结构方式 12.3 ODBC介绍 12.4 ODBC工作流程 12.5 ODBC编程示例 本章小结,12.1 调用层接口概述,背景 人机交互和自含式数据交换适用于单机或集中式结构 传统的数据与应用捆绑的方式不适合网络环境 将数据与应用分离,再通过接口将其连接起来 可用专用的接口工具连接应用结点和数据结点 通过应用程序调用接口的方式实现数据交换 称为调用层接口,12. 1 调用层接口概述,标准及产品 SQL99中的SQL/CLI,国际标准 ODBC,(开放式数据库互连)微软标准 JDBC,UNIX下基于jav
2、a的标准,12. 2 C/S结构方式,服务器S,客户机C,客户机C,客户机C,图12.1 C/S结构示意图,12.2 C/S结构方式,功能划分 服务器上存放数据库,完成相应的存储逻辑功能 客户端完成应用逻辑及表示逻辑的功能(业务流程及界面显示) 优点 数据共享 结构灵活 分布均匀,12. 3 ODBC介绍,数据源,Oracle 数据源,Sybase 数据源,SQL server 数据源,DB2 数据源,应用程序,驱动程序管理器,驱动程序,oracle 驱动程序,sybase 驱动程序,DB2 驱动程序,图12.2 ODBC结构示意图,SQL server 驱动程序,12.3 ODBC介绍,体系
3、结构 应用程序 调用ODBC函数,实现连接数据源 递交SQL语句(以ODBC参数形式出现) 返回数据的接收处理 断开连接 驱动程序管理器 连接管理各种DBMS的驱动程序,12.3 ODBC介绍,驱动程序 针对固定数据源的ODBC函数执行代码 供应用程序调用 一个ODBC接口可有若干驱动程序 数据源 提供数据 可以是各种类型的数据库 或文件结构,12.3 ODBC介绍,ODBC接口 完成应用程序与数据源之间的连接与断开 完成主程序变量与SQL参数之间的接口 完成SQL中集合量与主程序中标量间的接口 完成主程序与SQL中的反馈信息的传递,连接管理,动态SQL,游标,诊断,12.4 ODBC工作流程
4、,1准备阶段 安装ODBC驱动程序 配置数据源 2链接库和头文件设置 SQL.h SQLTYPES.h SQLEXT.h ODBCSS.h ODBCINST.h SQLUCODE.h,12.4 ODBC工作流程,3 连接阶段 4 执行SQL语句 5 结束阶段,12. 4 ODBC工作流程,SQLAllocHandle,SQLAllocHandle,分配环境句柄,分配连接句柄,SQLConnect,SQLAllocHandle,分配语句句柄,连接,12.4 ODBC工作流程,SQLPrepare,SQLExecute,SQLExecDirect,SQLFetch,SQLGetcol,循环,执行,
5、循环结束,12.4 ODBC工作流程,SQLFreeHandle,SQLDisconnect,结束,SQLFreeHandle,SQLFreeHandle,释放语句句柄,释放连接句柄,释放环境句柄,12.4 ODBC工作流程,ODBC应用程序基本结构示例/*头文件*/#include #include #include #include #include #include #include ,12. 4 ODBC工作流程,SQLHENV henv = SQL_NULL_HENV; /*定义环境句柄变量*/ SQLHDBC hdbc = SQL_NULL_HDBC; /*定义连接句柄变量*/ S
6、QLHSTMT hstmt = SQL_NULL_HSTMT; /*定义语句句柄变量*/ /*主函数*/ int main() ,12.4 ODBC工作流程,SQLRETURN retcode;/*定义返回代码变量*/ UCHA szDSNSQL_MAX_DSN_LENGTH+1=”Db_SQL”,/*数据源为Db_SQL*/szUIDMAXNAME=”myname”,/*登录用户名为myname*/szAuthStrMAXNAME=”mypassword”; /*用户密码是mypassword*/,12. 4 ODBC工作流程,/*分配ODBC环境句柄henv*/ retcode=SQLAl
7、locHandle (SQL_HANDLE_ENV, NULL, ,12. 4 ODBC工作流程,/*连接数据源*/ retcode=SQLConnect(hdbc,szDSN,(SWORD)strlen(szDSN),szUID,(SWORD)strlen(szUID),szAuthStr, (SWORD)strlen(szAuthStr); /*检测连接是否成功*/ if (retcode!=SQL_SUCCESS) /*连接成功*/,12. 4 ODBC工作流程,/*分配语句句柄hstmt*/ retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc,
8、 /*设置语句句柄属性,并进行SQL处理*/,12.4 ODBC工作流程,/*结束阶段*/ SQLFreeHandle(SQL_HANDLE_STMT, hstmt); /*释放语句句柄hstmt*/ SQLDisconnect(hdbc); /*断开数据源*/ SQLFreeHandle(SQL_HANDLE_DBC, hdbc);/*释放连接句柄*/ SQLFreeHandle(SQL_HANDLE_ENV, henv); /*释放环境句柄*/ return(0); ,3连接阶段,(1)分配句柄 分配环境句柄和连接句柄 调用同一个函数,参数不同 SQLRETURN SQLAllocHand
9、le (SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE* OutputHandlePtr) 在分配句柄之前,需要先声明一个句柄变量SQLHENV henv /声明环境句柄变量SQLHDBC hdbc /声明连接句柄变量,3连接阶段,(2)设置属性 设置环境属性SQLRETURN SQLSetEnvAttr (SQLHENV EnvironmentHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLength) 如果想了解当前环境的属性设置,可调用 SQL
10、GetEnvAttr函数,3连接阶段,设置连接属性SQLRETURN SQLSetConnectAttr (SQLHDBC ConnectionHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLength) 如果想了解当前连接的属性设置,可调用 SQLGetConnectAttr函数,3连接阶段,(3) 连接数据源 SQLRETURN SQLConnect (SQLHDBC ConnectionHandle,SQLCHAR* ServerName,SQLSMALLINT NameLength1,SQLCHAR*
11、UserName,SQLSMALLINT NameLength2,SQLCHAR* Authentication,SQLSMALLINT NameLength3),3连接阶段,(4)初始化 分配语句句柄 调用函数SQLAllocHandle , HandleType参数的取值为SQL_HANDLE_STMT SQLHSTMT hstmt; /*声明语句句柄变量 设置语句句柄属性SQLRETURN SQLSetStmtAttr (SQLSTMT StatementHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLe
12、ngth),4 执行SQL语句,(1)直接执行 适用于单次执行SQLRETURN SQLExecDirect(SQLHSTMT StatementHandle,SQLCHAR* StatementText,SQLINTEGER TextLength) 例:retcode=SQLExecDirect(hstmt,”SELECT * FROM book WHERE name=数据库技术实用教程”,SQL_NTS);,4 执行SQL语句,(2)准备执行SQLRETURN SQLPrepare(SQLHSTMT StatementHandle,SQLCHAR* StatementText,SQLINT
13、EGER TextLength) SQLRETURN SQLExecute (SQLHSTMT StatementHandle),4 执行SQL语句,例:Retcode= SQLPrepare(hstmt,”select * from book where name=数据库应用”,SQL_NTS);Retcode=SQLExecute(hstmt); 注意: 执行SQLExecDirect和SQLExecute语句时,系统会自动创建游标并打开 在多次执行时,要调用SQLCloseCursor将与该句柄相关联的游标关闭,4 执行SQL语句,(4)参数绑定 应用程序与动态SQL语句中参数标记的绑定
14、 调用SQLBindParameter函数完成 变量绑定,执行一次就要传递一次参数 大批量数据传递采用数据绑定方式 列式绑定 行式绑定 结果集合与应用程序变量的绑定 调用SQLBindCol函数完成 列式绑定 行式绑定,4 执行SQL语句,(5)结果集合的处理 在SQL Server2000中使用游标时,不需要用到declare和open语句,系统会自动创建并打开 获取数据 SQLFetch 从结果集中读取当前行中的数据,将游标推进一个行 当游标到结果集结尾时,返回SQL_NO_DATA SQLFetchScroll 从结果集中读取指定行中的数据,4 执行SQL语句,(6)错误诊断 SQL_S
15、UCCESS:函数执行成功; SQL_SUCCESS_WITH_INFO:函数执行成功,可能有一条不致命的错误(警告); SQL_NO_DATA:没有更多的数据可用,说明结果集中的行都已经检索完;,4 执行SQL语句,SQL_STILL_EXECUTING:一个异步开始的函数还在执行; SQL_ERROR:函数执行失败; SQL_NEED_DATA:需要更多数据,说明需要更多的参数数据或连接信息; SQL_INVALID_HANDLE:由于使用了无效的句柄导致函数执行失败。,5结束阶段,释放句柄 SQLRETURN SQLFreeHandle (SQLSAMLLINT HandleType,S
16、QLHANDLE Handle) 断开与数据源的连接 SQLRETURN SQLDisconnect( SQLHDBC ConnectionHandle),12.5 ODBC编程示例,例:使用ODBC编程实现计算职工年终奖金的应用需求 计算公式:月基本工资*12*15%*系数-(病事假天数*50元),其中系数:处级1、科级0.8、科员0.5、工人0.4。,12.5 ODBC编程示例,奖金表结构salary设计如下表:,12. 5 ODBC编程示例,在上表中前四项数据已存在,需计算后一项数据(即年度奖金),其奖金清单的原始数据如图所示。 要求实现从salary表中读取相应数据,按照年终奖金计算公
17、式进行计算处理。,12. 5 ODBC编程示例,12.5 ODBC编程示例,/*头文件*/#include #include #include #include #include #include #include #include ,12. 5 ODBC编程示例,SQLHENV henv = SQL_NULL_HENV; /*定义环境句柄变量*/SQLHDBC hdbc = SQL_NULL_HDBC;/*定义连接句柄变量*/SQLHSTMT hstmt = SQL_NULL_HSTMT;/*定义语句句柄变量*/ SQLHSTMT hstmt2 = SQL_NULL_HSTMT;/*定义语句
18、句柄变量*/,12.5 ODBC编程示例,int main() /*声明及定义变量*/SQLRETURN retcode;SQLCHAR name1050;SQLINTEGER times10;float basic_salary10;SQLCHAR job_level1050;float year_bonus10;SQLUSMALLINT Status10;SQLUINTEGER NumRowsFetched;SQLINTEGER name_len10, time_len10, basic_salary_len10, job_level_len10, year_bonus_len10;,12
19、.5 ODBC编程示例,/*分配ODBC环境句柄henv*/retcode =SQLAllocHandle (SQL_HANDLE_ENV, NULL, ,12.5 ODBC编程示例,/*连接数据源,数据源为Db_SQL,登录用户名为myname,密码为mypassword*/retcode=SQLConnect(hdbc,(SQLCHAR*)“Db_SQL”,SQL_NTS,(unsigned char*)“myname”, SQL_NTS, (unsigned char*)“mypassword”, SQL_NTS);,12. 5 ODBC编程示例,/*检测连接是否成功*/if (retc
20、ode!=SQL_SUCCESS) ,12.5 ODBC编程示例,/*分配语句句柄hstmt*/retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, ,12.5 ODBC编程示例,/*设置语句句柄属性*/SQLSetStmtAttr(hstmt,SQL_ATTR_CURSOR_TYPE,(SQLPOINTER) SQL_SCROLLABLE , 0);SQLSetStmtAttr(hstmt,SQL_ATTR_CONCURRENCY,(SQLPOINTER) SQL_CONCUR_LOCK, 0);SQLSetStmtAttr(hstmt,SQL_AT
21、TR_ROW_BIND_TYPE,(SQLPOINTER) SQL_BIND_BY_COLUMN, 0);SQLSetStmtAttr(hstmt,SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);SQLSetStmtAttr(hstmt,SQL_ATTR_ROW_STATUS_PTR, Status, 0);SQLSetStmtAttr(hstmt,SQL_ATTR_ROWS_FETCHED_PTR, ,12.5 ODBC编程示例,/*执行SQL语句,获得结果集*/retcode = SQLExecDirect(hstmt, (unsigned char
22、 *)“SELECT name, basic_salary, job_level, times FROM salary“, SQL_NTS);,12.5 ODBC编程示例,/*绑定列*/SQLBindCol(hstmt,1,SQL_C_CHAR,name,50, name_len);SQLBindCol(hstmt,2,SQL_C_FLOAT,basic_salary,sizeof(basic_salary0),basic_salary_len);SQLBindCol(hstmt,3,SQL_C_CHAR,job_level,50,job_level_len);SQLBindCol(hstmt
23、,4,SQL_C_SLONG,times,sizeof(times0),time_len);,12.5 ODBC编程示例,/*读取数据并进行计算处理*/while(retcode=SQLFetchScroll(hstmt,SQL_FETCH_NEXT,0) = = SQL_SUCCESS )for ( int i = 0; i NumRowsFetched; i+ ),12.5 ODBC编程示例,/*判断系数*/float param = 0.4;if ( strcmp(const char *)job_leveli, “处级“) = = 0 ) param = 1; else if ( st
24、rcmp(const char *)job_leveli, “科级“) = = 0 ) param = 0.8; else if ( strcmp(const char *)job_leveli, “科员“) = = 0 ) param = 0.5; ,12.5 ODBC编程示例,/*计算年终奖金*/year_bonusi = param * 12 * 0.15 * basic_salaryi - timesi * 50; SQLCloseCursor(hstmt);,12.5 ODBC编程示例,/*结束阶段*/SQLFreeHandle(SQL_HANDLE_STMT, hstmt); /*释放语句句柄hstmt*/SQLDisconnect(hdbc); /*断开数据源*/SQLFreeHandle(SQL_HANDLE_DBC, hdbc); /*释放连接句柄*/SQLFreeHandle(SQL_HANDLE_ENV, henv); /*释放环境句柄*/return(0); ,本章小结,C/S结构方式 数据与应用程序分离 调用层接口出现 ODBC接口 ODBC结构原理 ODBC工作流程 连接 应用程序与数据源交互 断开连接,