数据库概论第八章数据库编程-补充材料-ODBC.ppt
8.3 ODBC 编程,*为何仍使用ODBC1997和1998年,Microsoft重点从DB-Library转变到OLE DB,从ODBC转变到ADO。ODBC可能并不是COM应用程序访问方法的选择,但如果用户有应用程序使用ODBC接口,或者使用传统结构编写新应用,就该考虑ODBC作为数据访问解决方法。,8.3.1 ODBC简介,实际上,SQL Server的客户管理和客户工具自身便使用ODBCODBC是一种低级的、紧密聚合的API,在与ADO比较和提供更高的对数据库控制的接口方面显得贫乏,但是是相对易学易用的技术。,8.3.1 ODBC简介,ADO不能达到ODBC所获得的支持程度,当访问的数据不存在OLE DB提供者,ADO还要使用ODBC接口ODBC仍是最有效的、最简单的并得到最好技术支持的技术,8.3.2 ODBC结构层次,ODBC体系结构由四部分构成:应用程序(客户端)驱动程序管理器数据库驱动程序数据源(数据库服务器),8.3.2 ODBC结构层次,SQLServer数据源,ORACLE数据源,FoxPro数据源,8.3.2 ODBC结构层次,应用程序(客户端)通常是用户的代码,并且生成SQL命令让服务器方执行。数据源(数据库服务器)执行SQL询问的数据库管理者。它与客户之间便是ODBC,8.3.2 ODBC结构层次,驱动程序管理器 是ODBC的交通引导者。当一个应用程序请求对其数据源的连接,驱动程序管理器读取该数据源的描述,定位并加载适当的驱动程序,管理应用程序和驱动程序的连接。,8.3.2 ODBC结构层次,数据库驱动程序 通常由数据库厂商提供,实现必须的解释和通信所需要的功能,将ODBC SQL 语法翻译成服务器专用的SQL,将查询交付服务器并接收返回结果和状态信息。,8.3.3 ODBC数据库应用程序,功能:调用ODBC函数,递交SQL语句给DBMS,检索出结果,并进行处理。主要完成ODBC外部接口的所有工作。主要操作:连接数据库向数据源发送SQL语句为SQL语句执行结果分配存储空间,定义读取的数据格式,8.3.3 ODBC数据库应用程序,读取结果处理错误如果需要,向用户提交处理结果请求事务的提交和回退操作断开与数据源的连接,8.3.3 ODBC数据库应用程序,应用程序提供图形用户界面(GUI)和事务逻辑,它是使用诸如Java、Visual Basic及C+这样的语言编写的程序。应用程序利用ODBC接口中的ODBC功能与数据库进行操作。,8.3.4 驱动程序管理器,是一个动态链接库(DLL),用于连接各种DBS的DBMS驱动程序(如Oracl、Foxpro、Sybase等驱动程序),管理应用程序和DBMS驱动程序之间的交互作用。,8.3.4 驱动程序管理器,功能:为应用程序加载DBMS驱动程序 检查ODBC调用参数的合法性和记录ODBC函数的调用 为不同驱动程序的ODBC函数提供单一的入口 调用正确的DBMS驱动程序 提供驱动程序信息,数据库驱动程序,ODBC应用程序不能直接存取数据库,其各种操作请求由驱动程序管理器提交给DBMS驱动程序,通过驱动程序实现对数据源的各种操作,数据库的操作结果也通过驱动程序返回给应用程序 数据库驱动程序被编译成为动态链接库,数据库驱动程序,作用:建立与数据源的连接向数据源提交执行的SQL语句对往返数据进行格式、类型转换向应用程序返回处理结果将DBMS返回错误转为ODBC错误码返给程序声明使用游标,数据库驱动程序,类型:单层驱动程序多层驱动程序 1单层驱动程序不仅要处理ODBC调用,还要解释执行SQL语句,即执行DBMS功能,例XBASE即单层*利用它编写的程序为非C/S结构*程序既可运行于单机,也可运行于网络环境,数据库驱动程序,图单机下基于单层驱动程序的应用程序结构,数据库驱动程序,图。网络环境下基于单层驱动程序的应用程序结构,网络,文件服务器,数据库驱动程序,8.3.多层驱动程序:只处理程序的ODBC函数调用和数据转换,将SQL语句传递给数据源服务器,由DBMS执行SQL,实现用户的各种操作请求。*SQL Server 属于多层驱动程序*基于此程序为C/S结构多层驱动程序与DBMS的功能是分离的,基于多层ODBC驱动程序的数据库应用程序适合于C/S结构,基于多层驱动程序的应用程序结构,8.3.6 ODBC数据源管理,数据源(Data Source Name:DSN)是数据库驱动程序与数据库系统连接的桥梁,数据源不是数据库系统(DBS),而是用于表达一个ODBC驱动程序和DBMS特殊连接的命名。可以将数据源名看成是与一个具体数据库建立的连接。它为ODBC驱动程序指出数据库服务器名称,以及用户的默认连接参数等。在开发ODBC应用程序时首先建立数据源。,8.3.6 ODBC数据源管理,数据源分三类用户数据源:只有创建数据源的用户才可以使用自己创建的DSN系统数据源:所有用户和在WindowsNT下的服务方式运行的应用程序均可使用。一般建此文件数据源:是ODBC3.0以后版添加的一种数据源,所有安装了相同数据库驱动程序的用户均可共享文件数据源,使用它有利于ODBC数据库应用程序的分发。,8.3.6 ODBC数据源管理,建立数据源步骤:1.查看已安装的数据库驱动程序8.3.创建新数据源3.建立ODBC函数调用日志,查看已安装的数据库驱动程序,创建新数据源,建立ODBC函数调用日志,8.4 ODBC应用程序实现,3.1ODBC句柄应用程序实现对数据源访问的第一步就是连接数据源,ODBC句柄是应用程序和数据源连接的工具。一个ODBC句柄就是一个应用程序变量,系统用来存储关于应用程序的上下文信息和应用程序所用到的一些对象。应用程序不需要知道句柄的内容,也不能直接操作被句柄所引用的内容。,8.4.1ODBC句柄,ODBC使用三个句柄:环境句柄、连接句柄和语句句柄,他们之间的关系如图:环境句柄:定义一个数据库环境连接句柄:定义一个数据库连接语句句柄:定义一条SQL语句,8.4.1ODBC句柄,8.4.1ODBC句柄,8.4.2 ODBC应用程序的基本流程,8.4.2 ODBC应用程序的基本流程,1.应用程序四阶段 1)连接阶段申请ODBC环境句柄;设置ODBC环境属性申请连接句柄建立与数据源的连接:设置连接属性,8.4.2 ODBC应用程序的基本流程,2)初始化阶段检索驱动程序和数据源的支持能力(SQL Getlnfo)申请语句句柄设置语句属性3)程序主体执行语句、处理结果、提交业务实现应用程序功能,8.4.2 ODBC应用程序的基本流程,4)结束部分释放语句句柄断开与数据库连接释放连接句柄和环境句柄,8.4.3 ODBC部分函数,ODBC3.x中,应用程序调用SQLAllocHandle函数可以申请环境句柄、连接句柄、语句句柄或描述符句柄。申请句柄函数语法格式:SQLRETURN SQLAllocHandle SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE*OutputHandlePtr,8.4.3 ODBC部分函数,HandleType参数值:SQL_HANDLE_ENV:环境句柄SQL_HANDLE_DBC:连接句柄SQL_HANDLE_STMT:语句句柄,8.4.3 ODBC部分函数,释放句柄函数语法格式:SQLRETURN SQLFreeHandle SQLSMALLINT HandleType,SQLHANDLE Handle,8.4.3 ODBC部分函数,8.3.连接驱动程序和数据源在分配了环境句柄和连接句柄之后,就可以准备与ODBC的数据源连接。ODBC规范定义了三种连接函数:SQLConnect、SQLDriverConnect、SQLBrowserConnect,8.4.3 ODBC部分函数,SQLRETURN SQLConnect(SQLHDBC ConnectionHandle,SQLCHAR*ServerName,SQLSMALLINT NameLength1,SQLCHAR UserName,SQLSMALLINT NameLength2,SQLCHAR Authentication,SQLSMALLINT NameLength3),8.4.3 ODBC部分函数,2)断开数据源函数 SQLDisconnect(hdbc)hdbc:要断开的连接句柄,8.4.3 ODBC部分函数,3.SQL语句的执行1)立即执行SQL语句的函数SQL语句经驱动程序分析后立即提交给数据源执行 SQLExecDirect(hstmt,szSqlStr,cbSqlStr)hstmt一个有效语句句柄szSqlStr,cbSqlStr:将要执行的SQL语句的字符串及其长度如:retcode=SQLExecDirect(hstmt,”SELECT*FROM S”,SQL_NTS)SQL_NTS:字符串长度,8.4.3 ODBC部分函数,2)准备执行的SQL语句的函数 此方式下,执行一条SQL语句需两步:a.准备:调用SQLPrepare函数编译SQL语句 b.执行:调用SQLExecute函数执行编译后产生的SQL语句访问计划,8.4.3 ODBC部分函数,语法:准备函数:SQLPrepare(hstmt,szSqlStr,cbSqlStr)执行函数:SQLExecute(hstmt),8.4.3 ODBC部分函数,SQLExecute函数可以多次执行SQLPrepare函数编译好的SQL语句,每次执行时可以使用不同的参数;与立即执行方式相比,SQLExecute函数要快,因为省去了驱动程序和数据源对SQL语句的处理时间;,8.4.3 ODBC部分函数,例.带参数的SQL语句SQLHSTMT hstmt;SQLCHAR*Statement=“INSERT publishers(pub_id,pub_name)VALUES(?,?)”;SQLCHAR ID5,Name41;SQLPrepare(hstmt,Statement,SQL_NTS);SQLBindParameter(hstmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,4,0,ID,sizeof(ID),SQL_NTS);,8.4.3 ODBC部分函数,SQLBindParameter(hstmt,2,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,40,0,Name,sizeof(Name),SQL_NTS);while(UserInput(ID,Name)/接收用户输入SQLExecute(hstmt);,8.4.3 ODBC部分函数,究竟采用哪种,主要考虑语句是否要多次执行,下列情况应使用准备执行方式:a.SQL语句需要多次执行,每次执行时可能要修改参数 b.应用程序需要了解执行前语句的编译信息。,8.4.4 ODBC(C语言)应用程序举例,举例1(C语言)例.使用ODBC函数的应用程序实例#include#include#include#include#include SQLHENV henv=SQL_NULL_HENV;/环境变量SQLHDBC hdbc=SQL_NULL_HDBC;/连接变量SQLHSTMT hstmt=SQL_NULL_HSTMT;/语句句柄变量,8.4.4 ODBC(C语言)应用程序举例,main()SQLRETURN sqlreturn;/返回变量 sqlreturn=SQLAllocHandle(SQL_HANDLE_ENV,NULL,8.4.4 ODBC(C语言)应用程序举例,/设置环境属性 sqlreturn=SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);if(sqlreturn!=SQL_SUCCESS_WITH_INFO),8.4.4 ODBC(C语言)应用程序举例,/申请连接句柄 sqlreturn=SQLAllocHandle(SQL_HANDLE _DBC,henv,8.4.4 ODBC(C语言)应用程序举例,/连接数据源SQLDB sqlreturn=SQLConnect(hdbc,(SQLCHAR*)”SQLDB”,SQL_NTS,(unsigned char*)”sa”,SQL_NTS,NULL,SQL_NTS);if(sqlreturn!=SQL_SUCCESS_WITH_INFO),8.4.4 ODBC(C语言)应用程序举例,/申请语句句柄 sqlreturn=SQLAllocHandle(SQL_HANDLE_STMT,hdbc,/在这里插入SQL语句执行和结果处理代码/,8.4.4 ODBC(C语言)应用程序举例,/释放语句句柄 SQLFreeHandle(SQL_HANDLE_STMT,hstmt);SQLDisconnect(hdbc);/关闭与数据源的连接/释放连接句柄 SQLFreeHandle(SQL_HANDLE_DBC,hdbc);/释放环境句柄 SQLFreeHandle(SQL_HANDLE_ENV,henv);return 0;,8.4.4 ODBC(C语言)应用程序举例,举例2例.提取数据(C语言)#include#include#include#include#include#define MAXBUFLEN 1024SQLHENV henv=SQL_NULL_HENV;/环境变量SQLHDBC hdbc=SQL_NULL_HDBC;/连接变量SQLHSTMT hstmt=SQL_NULL_HSTMT;/语句句柄变量,8.4.4 ODBC(C语言)应用程序举例,int connect();void disconnect();void ErrorProcess(SQLSMALLINT handle_type,SQLHANDLE handle,char*logstring,int bConnected);#define ARRAY_SIZE 5#define AUTHOR_LEN 25#define PHONE_LEN 21,8.4.4 ODBC(C语言)应用程序举例,main()SQLRETURN sqlreturn;SQLCHAR Statement=“SELECT 作者=RTRIM(au_fname)+RTRIM(au_lname),电话=phone FROM pubs.authors”;SQLCHAR authorARRAY_SIZEAUTHOR_LEN;SQLCHAR phoneARRAY_SIZEPHONE_LEN;SQLUINTEGER i,RowFetched;SQLUINTEGER AuthorLenARRAY_SIZE,PhoneLenARRAY_SIZE;SQLSMALLINT FetchStatusARRAY_SIZE;,8.4.4 ODBC(C语言)应用程序举例,if(connect()return 1;/连接数据源失败sqlreturn=SQLAllocHandle(SQL_HANDLE_STMT,hdbc,8.4.4 ODBC(C语言)应用程序举例,SQLSetStmtAttr(hstmt,SQL_ATTR_CURSOR_TYPE,SQL_ CURSOR_FORWORD_ONLY,0);SQLExecDirect(hstmt,Statement,SQL_NTS);SQLSetStmtAttr(hstmt,SQL_ATTR_ROW_BIND_TYPE,SQL_BIND_BY_COLUMN,0);/将语句属性/设为列绑定SQLSetStmtAttr(hstmt,SQL_ATTR_ ROW_ ARRAY_SIZE,(SQLPOINTER)ARRAY_SIZE,0);/设置行集大小SQLSetStmtAttr(hstmt,SQL_ ATTR_ ROW_ STATUS_PTR,FetchStatus,0);/设置行集提取状态组,8.4.4 ODBC(C语言)应用程序举例,SQLSetStmtAttr(hstmt,SQL_ ATTR_ ROW_ FETCHED_PTR,while(sqlreturn=SQLFetch(hstmt)=SQL_SUCCESS|sqlreturn=SQL_SUCCESS_WITH_INFO),8.4.4 ODBC(C语言)应用程序举例,for(i=0;iRowFetched;i+)if(FetchStatutsi!=SQL_ROW_ERROR,