使用ODBC API 连接数据库(共24页)_第1页
使用ODBC API 连接数据库(共24页)_第2页
使用ODBC API 连接数据库(共24页)_第3页
使用ODBC API 连接数据库(共24页)_第4页
使用ODBC API 连接数据库(共24页)_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、主要(zhyo)内容: ODBC API的体系结构 使用(shyng)ODBC API开发数据库应用程序的一般步骤 使用(shyng)函数SQLAllocHandle分配句柄 使用函数SQLConnect、SQLDriverConnect、SQLBrowseConnect连接数据源 使用函数SQLPrepare和SQLExecute执行SQL语句 使用函数SQLBindCol()绑定数据库字段 使用函数SQLGetDiagRec和SQLGetDiagField处理错误 使用函数SQLFetch移动数据库记录指针 使用ODBC API 进行事务处理 使用函数SQLDisconnect断开数据源的

2、连接 目录(ml)TOC o 1-3 h u HYPERLINK l _Toc30793 ODBC API 基础(jch) PAGEREF _Toc30793 3 HYPERLINK l _Toc22242 ODBC API句柄 PAGEREF _Toc22242 3 HYPERLINK l _Toc5102 ODBC数据类型 PAGEREF _Toc5102 5 HYPERLINK l _Toc22898 ODBC诊断(zhndun) PAGEREF _Toc22898 5 HYPERLINK l _Toc15710 使用ODBCAPI变成建立应用程序 PAGEREF _Toc15710 7

3、 HYPERLINK l _Toc13536 ODBCAPI编程模型概述 PAGEREF _Toc13536 7 HYPERLINK l _Toc25206 连接数据库 PAGEREF _Toc25206 10 HYPERLINK l _Toc25488 准备并执行SQL语句 PAGEREF _Toc25488 14 HYPERLINK l _Toc12317 获取记录集 PAGEREF _Toc12317 16 HYPERLINK l _Toc21145 记录的添加、删除和更新 PAGEREF _Toc21145 18 HYPERLINK l _Toc11183 错误处理 PAGEREF _

4、Toc11183 20 HYPERLINK l _Toc5116 事务处理 PAGEREF _Toc5116 21 HYPERLINK l _Toc8412 断开数据源连接并释放环境句柄 PAGEREF _Toc8412 23ODBC API 基础(jch)ODBC API句柄ODBC API 实现数据库操作的手段是句柄。在ODBC中,使用不同的句柄(HANDLE)来标志环境(environment)、连接(Connection)、语句(statement)、描述符(description)等。句柄是一个应用程序变量,系统用它来存储(cn ch)关于应用程序的上下文信息和应用程序所用到的一些对

5、象。 1、 环境(hunjng)句柄 环境是存取数据的全局性背景,与环境相关的是全局的所有信息。例如:环境状态、当前环境状态诊断、当前在环境上分配的连接句柄、每个环境属性的当前设置。 在实现ODBC的一段代码(Driver Manager或者驱动程序)中,环境句柄标识包含这个信息的结构。环境句柄在ODBC应用程序中不经常用。他们经常用来调用SQLDataSources和SQLDrivers,又是用来调用函数SQLAllocHandle、SQLEndTran、SQLFreeHandle、SQLGetDiagField和SQLGetDiagReg。 环境句柄ODBC中整个上下文的句柄,使用ODBC

6、的每个程序从创建环境句柄开始、以释放环境句柄结束。所有其他的句柄都由环境句柄的上下文来管理。环境句柄在每个应用程序中只能创建一个。 2、 连接句柄 一个连接包含一个驱动程序和一个数据源。连接句柄标识每个连接。连接句柄定义使用哪个驱动程序和该驱动程序使用的数据源。在执行一段ODBC(Driver Manager或者驱动程序)的代码中,连接句柄标志一个包含连接信息的结构。比如:连接状态、当前连接层诊断、语句句柄和当前连接上分配的描述符、每个连接属性的当前设置。 如果驱动程序支持多个同时连接,ODBC并不阻止多个同时的连接。因此,在特定的ODBC环境中,多个连接句柄可能指向不同的驱动程序和数据源、相

7、同的驱动程序和不同的数据源甚至是与相同的驱动程序和数据源的多个连接。一些驱动程序限制他们支持的活动连接数目,SQLGetInfo中的SQL_MAX_DRIVER_CONNECTIONS选项可指定一个特定的驱动程序支持多少个活动连接。与数据源进行连接(SQLConnect、SQLDriverConnect或SQLBrowseConnect)、从数据源上断开(SQLDisconnect)、获取驱动程序及数据源信息(SQLGetInfo)、检索诊断(SQLGetDiagField和SQLGetDiagRec)和执行事务(SQLEndTran)时,都需要使用连接句柄。当设置和获取连接属性(SQLSet

8、ConnectAttr)及获取SQL语句内部格式(SQLNativeSql)时,也使用它们。 在应用程序中,可在任何适当的时候连接或脱离(tul)数据源,但不要轻易的建立或脱离连接。 3、 语句(yj)句柄 一个语句不只是一个SQL语句,它包含所有与那个SQL语句相关的信息,如任何由语句和语句执行中使用的参数建立的结果集。一个语句甚至(shnzh)不需要应用程序的SQL语句。例如,当在一个语句上执行如SQLTables这样的编目函数时,它执行返回表名列表的预定义SQL语句。 每个语句由语句句柄标识。一个语句与单个的连接相关,并且在那个连接上可能有多个语句。一些驱动程序限制它们支持活动语句的数目

9、,在SQLGetInfo中SQL_MAX_CONCURRENT_ACTIVITIES选项指定一个驱动程序在单个的连接上支持多少个活动的语句。如果它的结果是未确定的,那么语句被定义成“活动的”,其结果既不是结果集,也不是受INSERT、UPDATE、或DELETE语句影响的行数,或者用多个调用把数据发送到SQLPutData。 在实现ODBC(Driver Manager或驱动程序)的一段代码中,语句句柄标识一个包含语句信息的结构,如:语句状态、当前语句层诊断、应用程序变量绑定到语句参数和结果集列的地址、每个语句属性的当前设置。 语句句柄在大多数ODBC函数中使用,它们用于函数绑定参数及结果集列

10、(SQLBindParameter和SQLBindCol)、准备执行语句(SQLPrepare、SQLExecute和SQLExecDirect)、检索元数据(SQLColAttribute和SQLDescribeCol)、取结果(SQLFetch)和检索诊断(SQLGetDiagField和SQLGetDiagRec)。它们还在编目函数(SQLColumns,SQLTables等)和其他一些函数中使用。语句句柄使用SQLAllocHandle分配,使用SQLFreeHandle释放。 4、 描述符句柄 从应用程序或驱动程序来看,描述符就是描述SQL语句的参数或结果集列的元数据集合。因此,描述

11、符可用来担当如下4种角色: 1) 应用程序参数描述符(APD):包含绑定到SQL语句中参数的应用程序缓冲区的信息,如它们的地址、长度和C数据类型。 2) 实现参数描述符(IPD):包含关于SQL语句中参数的信息,如它们的SQL数 据类型、长度、和可控性(nullability)。 3) 应用程序行描述符(ARD):包含绑定到结果集列的应用程序缓冲区的信息, 如它们的地址、长度和C数据类型。 4) 实现行描述符(IRD):包含结果集中列的信息,如它们的SQL数据类型、长 度、和可控性。 四种描述符(一种承担一个角色)在分配语句时自动分配,且总是与那条语句相关。称为自动分配描述符。应用程序还可用S

12、QLAllocHandle分配描述符,称为显示分配描述符。它们根据连接进行分配,并且可以与那个连接上的一条或多条语句关联,来履行那些语句上的APD或ARD的职责。 应用程序可完成ODBC中的大多数操作,而不明确使用描述符。然而,描述符可以为有些操作提供方便的快捷方式。例如,假设一个应用程序想从两套不同的缓冲区插入数据。要用第一套缓冲区,它会反复调用SQLBindParameter来把它们绑定至INSERT语句的参数中,然后再执行该语句。要使用第二套缓冲区,它就会重复这个过程。另一种方法就是在一个描述符中建立起对第一套缓冲区的绑定,在另一个描述符中建立对第二套缓冲区的绑定。要在两套绑定集间切换,

13、只需调用SQLSetStmtAttr,并把正确(zhngqu)的描述符作为APD与语句联系起来即可。 ODBC数据类型 ODBC使用(shyng)两套数据类型:SQL数据类型和C数据类型。SQL数据类型用于数据源,而C数据类型用于应用程序的C代码。 1、 SQL数据类型 SQL数据类型是在数据源中保存的数据类型。每个数据源都定义了它自己的SQL数据类型。ODBC定义类型标识符并且(bngqi)描述可能映射为每一种类型标识符的SQL数据类型的一种特征。在基本数据源中,每一种数据类型如何映射为ODBC的SQL类型标识符是由驱动程序制定的。 ODBC中定义的常用SQL数据类型如表所示,此处列出了部分

14、常用的类型,详细资料参见ODBC的技术手册:SQL类型标识SQL类型举例SQL_CHARCHAR(n) SQL_VACHAR VACHAR(n)SQL_LONGVACHAR LONG VACHARSQL_WCHARWCHAR(n)2、 C数据类型 ODBC定义了由应用程序变量及其相应的数据标识符所使用的C数据类型。在其他的事情中,它们也用于绑定至结果集列和语句参数的缓冲区。ODBC还定义了一个从每个数据类型到一个C数据类型的默认映射。要使用默认映射,应用程序可指定SQL_C_DEFAULT类型标识符。但是,出于互操作性的原因,不主张使用这个标识符。在ODBC 1.x版本中定义的所有整数C数据类

15、型都是带符号的。在ODBC 2.0中添加了不带符号的C数据类型及其相应的数据标识符。 ODBC中定义的常用C数据类型如表所示,此处列出了部分常用的类型,详细资料参见ODBC的技术手册: C类型标识ODBC C类型定义C类型SQL_C_CHARSQLCHARUnsigned char *SQL_C_SSHORTSQLSMALLINTShort intSQL_C_USHORTjSQLUSMALLINTUnsigned short intSQL_C_SLONGjSQLINTEGERLong intODBC诊断(zhndun) 为了在程序开发过程(guchng)中调试程序,发现程序错误,ODBC AP

16、I 通过两种方式返回有关ODBC API函数执行的信息:返回码和诊断记录。返回码返回函数执行的返回值,说明函数执行成功与否;诊断记录说明函数执行的详细信息。 1、 返回(fnhu)码(Return Code) 每一个ODBC API函数都返回一个代码返回码,指示函数执行的成功与否。如果函数调用成功,返回码为SQL_SUCCESS(指示可通过诊断记录获取相关操作的详细信息)或SQL_SUCCESS_WITH_INFO(指示应用程序执行结果带有警告信息,可通过诊断记录获取详细的信息)。如果函数调用失败,返回码为SQL_ERROR。 下面一段代码根据函数SQLFetch()执行的返回码,判断函数执行

17、的成功与否,从而据此进行相应的处理: SQLRETURN rtcode; SQLHSTMT hstmt; While(rtcode = SQLFetch(hstmt) != SQL_NO_DATA) If(rtcode = SQL_SUCCESS_WITH_INFO) /显示警告信息 else /显示出错信息 break; /函数调用成功 如果程序执行错误,返回码为SQL_INVALID_HANDLE,程序无法执行,而其他的返回码都带有程序执行信息。 2、 诊断记录 每个ODBC API函数都能产生一系列的反应操作信息的诊断记录,这些诊断记录都放在相关联的ODBC句柄中,直到下一个使用同一个句

18、柄的函数调用,该诊断记录一直存在。诊断记录的大小没有限制。 诊断记录有两种:头记录(Head Record)和状态(zhungti)记录(Status Record)。头记录是第一版权记录(Record0),后面的记录为状态记录。诊断记录有许多的域组成,这些域在头记录和状态记录中是不同的。 可以用SQLGetDiagField函数获取诊断记录中的特定的域,另外,可以使用SQLGetDiagRec()函数获取诊断记录中一些常用的域,如SQLSTATE、原始(yunsh)错误号等。 (1) 头记录(jl) 头记录的各个域中包含了一个函数执行的通用信息,无论函数执行成功与否,只要不返回SQL_INV

19、ALID_HANDLE,都会生成头记录。 (2) 状态记录 状态记录中的每个域包含了驱动管理器、ODBC驱动程序或数据源返回的特定的错误或警告信息,包括SQLSTATE、原始错误码、诊断信息、列号和行号等。只有函数执行返回SQL_ERROR、SQL_STILL_EXEUTING、SQL_SUCCESS_WITH_INFO、SQL_NEED_DATA或SQL_NO_DATA时,才会生成诊断记录。 (3) 使用SQLGetDiagRec和SQLGetDiagField 应用程序可以调用SQLGetDiagRec和SQLGetDiagField函数获取诊断信息。对于给定的句柄,这两个函数返回最近使用

20、句柄的函数的诊断信息。当有使用该句柄的函数执行时,句柄记录所记录的原有的诊断信息被覆盖。如果函数执行后产生多个状态记录,程序必须多次调用这两个函数以获取信息。例如,下面的代码提示符提供给用户使用SQL语句并执行它。如果返回一些真消息,则它调用SQLGetDiagField来取得状态记录书并调用SQLGetDiagRec来从那些记录中取得SQLSTATE、本地错误代码、诊断消息:SQLCHARsqlState6,SQLStmt100,MsgSQL_MAX_MESSAGE_LENGTH;SQLINTRGERNativeError;SQLSMALLINTI,MsgLen;SQLRETURNrc1,r

21、c2;SQLHSTMEHstmt;/PrompttheuserforanSQLstatementGetSQLStmt(SQLStmt);/执行SQL语句返回错误结果rc1=SQLExecDirect(hstmt,SQLStmt,SQL_NTS);if(rc1=SQL_SUCCESS_WITH_INFO)|(rc1=SQL_ERROR)/得到状态记录 i=1;while(rc2=SQLGetDiagRec(SQL_HANDLE_STMT,hstmt,i,SqlState,&NativeError,Msg,sizeof(Msg),&MsgLen)!=SQL_NO_DATA)DisplayError

22、(SqlState,NativeError,Msg,MsgLen);i+;if(rc1=SQL_SUCCESS)|(rc1=SQL_SUCCESS_WITH_INFO)/如果(rgu)必要就处理结果使用(shyng)ODBCAPI变成建立(jinl)应用程序ODBCAPI编程模型概述使用ODBC API编写的程序运行时相对要简洁、高效。一般,编写ODBC程序主要有以下几个步骤: 为ODBC分配环境句柄分配一个连接句柄 用SQL命令分配一个语句句柄 执行该命令返回结果集 断开同数据源的连接 释放ODBC环境 为了更清楚的阐述ODBC API的调用步骤以及涉及到的重要函数,总结了一 个表来说明OD

23、BC API应用的结构: SQLAllocHandle(ENV)SQLSetEnvAttrSQLAllocHandle(DBC)SQLConnectSQLSetConnectAttrSQLGetInfo SQLAllocHandle(STMT)SQLSetStmtAttrODBC初始化函数SQLExecDirectOR SQLPrepareSQLExecute使用ODBC API 检索数据Select OR Update/Delete/InsertSQLNumResultColsSQLBindCOL SQLFetchSQLGetDataSQLCloseCursor执行SQL语句使用结果集SQL

24、FreeHandle(STMT)SQLDisconnect SQLFreeHandle(DBC)SQLFreeHandle(ENV)释放空间所有(suyu)ODBC应用程序都必须遵循上图的通用ODBC API调用 注册数据源(Access数据库employers.mdb,其中只有一张表emp,包含三个字段:职工号、职工名称、工作) /添加(tin ji)ODBC数据源 void CDemo1App:SetODBCSource() CString strAccessPath = m_strExePath + “employers.mdb”; int iLen = strAccessPath.Ge

25、tLength(); char cpConfigMAX_PATH; /构造注册字符串 strcpy(cpConfig,“DSN = daliu0”); strcpy(cpConfig + 10, “DBC=”); strcpy(cpConfig + 14, strAccessPath); strcpy(cpConfig + 14 + iLen, “0”); strcpy(cpConfig + 15 + iLen, “DEFAULTDIR = ”); strcpy(cpConfig + 15 + iLen + 11, m_strExePath); strcpy(cpConfig + 25 + i

26、Len + m_strExePath.GetLength(), “00 ”); /注册数据源 if(!SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN, “Microsoft Access Driver(*.mdb)0”, cpConfig) /AfxMessageBox(“add odbc source failed!”); 连接数据库 连接数据库包括初始化环境句柄、初始化连接句柄以及连接数据源等几个步骤。 1、 初始化环境句柄 (1) 分配环境句柄 对于任何ODBC应用程序来说,第一步的工作(gngzu)是装在驱动程序管理器,然后初始化ODBC环境,分配

27、句柄 首先声明一个SQLHENV类型的变量,然后调用SQLAllocHandle,向其中传递分配的SQLHENV类型的变量地址(dzh)和SQL_HANDLE_ENV选项,代码如下: /分配(fnpi)环境句柄m_retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv); if(m_retcode != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) AfxMessageBox(“分配环境句柄失败”); return FALSE; 其中:m_henv是要分配的环境

28、句柄,m_retcode是返回码。 执行该调用语句后,驱动程序分配一个结构,该结构中存放环境变量,然后返回对应于该环境的环境句柄。 一个应用程序对应于一个环境,但是同一个环境可以用于不同数据源的连接,可以使用多个线程,应用程序完成数据访问任务,应调用函数SQLFreeHandle()函数释放当前分配的环境。 (2) 设置环境属性 应用程序在完成环境的分配后,接着调用函数SQLSetEnvAttr设置环境属性,注册ODBC的版本号,说明应用程序所遵从的标准是ODBC 2.x还是ODBC 3.x,相关代码如下所示。使用不同的版本,相同的参数作用会不相同,具体的说明参见MSDN。 /*设置ODBC版

29、本的环境属性*/ m_retcode=SQLSetEnvAttr(m_henv,SQL_ATTR_ODBC_VERSION,(void*)SQL_OV_ODBC3, 0); if(m_retcode != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) ReportError(m_henv, SQL_HANDLE_ENV, “设置ODBC版本号时失败”); return FALSE; 其中m_henv是环境句柄,m_retcode是返回码,ReportError是一个处理错误的函数。 2、 初始化连接句柄 (1) 分配连接句柄 分配环境句

30、柄之后,在建立至数据源的连接之前,必须分配一个连接句柄,每一个到数据源的连接对应于一个连接句柄。 首先,程序定义一个SQLHDBC类型的变量,用于存放连接句柄,然后调用SQLAllocHandle函数分配句柄。 /分配连接句柄 m_retcode = SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &m_hdbc);if(m_retcode != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) ReportError(m_henv, SQL_HANDLE_ENV, “分配(fnpi)连接句柄失败!”); re

31、turn FALSE; 其中m_henv是环境句柄,m_hdbc是要分配(fnpi)的连接句柄,m_retcode是返回码 (2) 设置(shzh)连接属性 连接属性表示了一个连接的特性,如登录等待时间、使用的光标库等。 所有的连接属性都有默认值,也可以通过调用函数SQLSetConnectAttr()设置,调用函数SQLGetConnectAttr()可获取这些连接属性的当前设置值,这两个函数定义如下: SQLSetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTR

32、GER StringLength ); SQLRETURN SQLGetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StringLengthPtr ); 3、 连接数据源 完成连接属性的设置之后,就可以建立到数据源的连接了。对于不同的程序和用户接口,可以用不同的函数建立连接:SQLConnect、SQLDriverConnect、SQLBrowseConnect (1) SQLConnect 该函数提供

33、了最为直接的程序控制方式,只要提供数据源名称、用户ID和口令,就可以进行连接了。其定义如下: SQLRETURN SQLConnect( SQLHDBC ConnectionHandle, /连接句柄 SQLCHAR *ServerName, /数据源名称 SQLSMALLINT NameLength1, /数据源名称长度SQLCHAR *UserName, /用户ID SQLSMALLINT NameLength2, /用户ID长度 SQLCHAR *Authentication, /用户口令 SQLSMALLINT NameLength3 /用户口令长度 ); /连接数据源 m_retco

34、de = SQLConnect(m_hdbc, (SQLCHAR *)cpServerName, SQL_NTS, (SQLCHAR *)cpUserName, SQL_NTS, (SQLCHAR *)cpPassword, SQL_NTS); if(m_retcode != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) ReportError(m_hdbc, SQL_HANDLE_DBC, “连接(linji)数据库失败!”); return FALSE; (2) SQLDriverConnect 该函数用一个连接字符串建立至数据源的

35、连接,他可以提供比SQLConnect函数的3个参数更多的信息,可以让用户输入必要(byo)的连接信息,使用系统中还没有定义的数据源。 如果连接建立,该函数会返回完整(wnzhng)的连接字符串,应用程序可以使用连接字符串建立额外的连接,其定义如下: SQLRETURN SQLDriverConnect( SQLHDBC ConnectionHandle; /连接句柄 SQLHWND WindowHandle; /窗口句柄,程序可以用父窗口的句柄或用空指针 SQLCHAR *InConnectionString; /一个指向连接字符串的指针 SQLSMALLINT StringLength1,

36、 /连接字符串长度 SQLCHAR *OutConnectionString; /一个指向连接字符串的指针 SQLSMALLINT BufferLength; /存放连接字符串的缓冲区的长度 SQLSMALLINT *StringLength2Ptr; /返回的连接字符串中的字符数 SQLUSMALLINT DriverCompletion /额外的连接信息,可能的取值:SQL_DRIVER_PROMPT、SQL_DRIVER_COMPLETE、SQL_DRIVER_COMPLETE_REQUIRED、 SQL_DRIVER_NOPROMPT); (3) SQLBrowseConnect 函数

37、SQLBrowseConnect支持以一种迭代的方式获取到数据源的连接,直到最后建立连接。它基于客户机/服务器体系结构,因此本地数据库(如Microsoft Access)不支持该函数。 一般,只提供部分连接信息,如果足以建立到数据源的连接,则成功建立连接,否则返回SQL_NEED_DATA,并在OutConnectionString参数中返回所需要的信息。其定义如下: SQLRETURN SQLBrowseConnect( SQLHDBC ConnectionHandle, /连接句柄 SQLCHAR *InConnectionString, /指向输入字符串的指针 SQLSMALLINT

38、StringLength1, /输入字符串的指针长度 SQLCHAR *OutConnectionString, /指向输出字符串的指针 SQLSMALLINT BufferLength, /存放输出字符串的缓冲区的长度 SQLSMALLINT *StringLength2Ptr /实际返回的字符串的长度 ); 连接数据库的完整代码: BOOL CMyODBC:ConnectDB(const char *cpServerName, const char *cpUserName, const char *cpPassword) /分配环境句柄 m_retcode = SQLAllocHandle

39、(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv); if(m_retcode != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) ) AfxMessageBox(“分配(fnpi)环境句柄失败!”); return FALSE; /*Set the ODBC version environment attribute*/ m_retcode = SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0); if(m_ret

40、code != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) ReportError(m_henv, SQL_HANDLE_ENV, “设置(shzh)odbc版本号时失败!”); return FALSE; /*分配(fnpi)连接句柄*/ m_retcode = SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &m_hdbc); if(m_retcode != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) ReportError(m_henv,

41、SQL_HANDLE_ENV, “分配连接句柄失败!”);return FALSE; /*连接数据库*/ m_retcode = SQLConnect(m_hdbc, (SQLCHAR *)cpServerName, SQL_NTS, (SQLCHAR *)cpUserName, SQL_NTS, (SQLCHAR *)cpPassword, SQL_NTS); if(m_retcode != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) eportError(m_hdbc, SQL_HANDLE_DBC, “连接数据库失败!”); r

42、eturn FALSE; return TRUE; 准备并执行SQL语句 1、 构造SQL语句 可以通过3种方式构造SQL语句: 在程序开发阶段确定:具有易于实现且可在程序编码时进行测试的优点 在运行时确定:提供了极大灵活性,但给程序带来了困难,却需要更多的处 理时间 由用户输入SQL语句:极大(j d)的增强了程序的功能,但是程序必须提供有好的 程序界面,且对用户输入的语句执行一定程序的语法检查,能够报告用户错误。 2、 执行(zhxng)SQL语句 (1) 分配(fnpi)语句句柄 语句句柄为ODBC驱动程序管理器提供数据结构,并跟踪SQL语句的执行机器返回的结果,语句句柄是通过调用SQL

43、AllocHandle函数分配的。下面的代码声明了一个存放语句句柄的变量m_hstmt,在函数中提供该变量的地址指针、所使用的连接句柄m_hdbc以及选项SQL_HANDLE_STMT: m_retcode = SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmt); if(m_retcode != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) ReportError(m_hdbc, SQL_HANDLE_DBC, “分配语句句柄失败,不能执行”); return FALSE; 函数SQLGe

44、tStmrrAttr()和SQLSetStmrrAttr()用来获取和设置一个语句句柄的选项,使用方式同前面的SQLGetConnectAttr()和SQLSetConnectAttr()函数相同。当一个语句句柄使用完成后,调用函数SQLFreeHandle()释放句柄。 (2) SQLExecDirect() SQLExecDirect()函数直接执行SQL语句,对于只执行一次的SQL语句来说,该函数是执行最快的方法,其定义如下: SQLRETURN SQLExecDirect(SQLHSTMT StatementHandle, /语句句柄 SQLCHAR *StatementText, /

45、要执行的SQL语句 SQLINTEGER TextLength /SQL语句的长度 );Demo1中使用该函数执行SQL语句的代码: m_retcode = SQLExecDirect(m_hstmt, (unsigned char *)cpSql, SQL_NTS); if(m_retcode != SQL_SUCCESS) & (retcode != SQL_SUCCESS_WITH_INFO) ReportError(m_hstmt, SQL_HANDLE_STMT, “执行SQL语句失败”); SQLFreeHandle(SQL_HANDLE_STMT, m_hstmt); m_hst

46、mt = NULL; return FALSE; (3) SQLPrepare()和SQLExecute() 对于需要多次执行的SQL语句来说,除了使用SQLExecDirect函数之外,也可以在执行SQL语句之前,先调用函数SQLPrepare()准备SQL语句的执行。对于使用参数的语句,这可大大提高程序的执行速度。而函数SQLExecute()用来执行一个准备好的语句,当语句中有参数时,用当前绑定的参数变量的值。其定义如下: SQLRETURN SQLPrepare(SQLHSTMT StatementHandle, /语句句柄 SQLCHAR *StatementText, /要执行的S

47、QL语句 SQLINTEGER TextLength /SQL语句(yj)的长度 ); SQLRETURN SQLExecute(SQLHSTMT StatementHandle); /语句(yj)句柄 (4) 使用(shyng)参数 使用参数可以使一条SQL语句多次执行,得到不同的结果,如下面的一条SQL语句: INSERT INTO EMP(职员号,职工名称,工作) VALUES(?,?,?) 该语句将向表emp中加入一条记录,通过参数替换(将句中问号出现的地方以相应的参数值替换),可以在程序运行的时候动态的添加多条记录。 SQL语句执行时,参数标识符(“?”)绑定程序中的变量,通过参数就

48、可以在程序执行时动态的将值传入SQL语句。 函数SQLBindParameter()负责为参数定义变量,将一段SQL语句中的一个参数标识符(“?”)绑定在一起,实现参数值的传递,其定义如下: SQLRETURN SQLBindParameter( SQLHSTMT StatementHandle, /语句句柄 SQLUSMALLINT ParameterNumber, /绑定的参数在SQL语句中的序号,在SQL 中,所有参数从左到右依次编号(从1开 始)。SQL语句执行之前,应该为每个参数调用函数SQLBindParameter绑定到某个程序变量。 SQLSMALLINT InputOutpu

49、tType, /参数类型,可为SQL_PARA_INPUT、SQL_PARAM_INPUT_OUTPUT、SQL_PARAM_OUTPUT SQLSMALLINT ValueType, /参数的C数据类型 SQLSMALLINT ParameterType, /参数的SQL数据类型 SQLUINTEGER ColumnSize, /参数的大小 SQLSMALLINT DecimalDigits, /参数的精度 SQLPOINTER ParameterValuePtr, /指向程序中存放参数值的缓冲区的指针 SQLINTEGER BufferLength, /程序中存放参数值的缓冲区的字节数 S

50、QLINTEGER *StrLen_or_IndPtr /指向存放参数ParameterValuePtr的缓冲区指针 ); 获取记录集 查询记录集是数据源上满足一定条件的数据记录的集合,在概念上,可以看成是一个临时存放返回结果的表。记录集可以是空。在用SQLExecDirect等函数执行SQL语句后,就可以从数据源中取回记录集。 1、 绑定列 从数据源取回的数据存放在应用程序定义的变量中,因此,必须首先分配与记录集中字段相对应的变量,然后通过函数SQLBindCol将记录字段同程序变量绑定在一起。对于长记录字段,可以通过调用函数SQLGetData()直接取回数据。 绑定字段可以根据自己的需要

51、全部绑定,也可以绑定其中的某几个字段。 记录集中的字段可以在任何时候绑定,但是,新的绑定只有当下一次从数据源中取数据时执行(zhxng)的操作才有效,而不会对已经取回的数据产生影响。 通过调用函数SQLBindCol将其变量地址赋值为NULL,可以结束对一个记录字段的绑定;通过调用函数SQLFreeStmt,将其中的选项设为SQL_UNBIND,或者(huzh)是直接释放句柄,都会结束所有记录字段的绑定。函数SQLBindCol的定义如下: SQLRETURN SQLBindCol( SQLHSTMT StatementHandle, /语句(yj)句柄 SQLUSMALLINT Column

52、Number, /标识要绑定的列号。数据列号从0开始升序排列,其中第0列用作书签,则列号从1开始 SQLSMALLINT TargetType, /数据类型 SQLPOINTER TargetValuePtr, /绑定到数据字段的缓冲区的地址 SQLINTEGER BufferLength, /缓冲区长度 SQLINTEGER *StrLen_or_IndPtr /指向绑定数据列使用的长度的指针 ); 2、 SQLFetch() 函数SQLFetch用于将记录集中的下一行变为当前行,并把所有捆绑过的数据字段的数据拷贝到相应的缓冲区,其定义如下:SQLRETURN SQLFetch(SQLHST

53、MT StatementHandle); /StatementHandle:语句句柄 3、 光标 应用程序获取数据是通过光标(Cursor)来实现的,在ODBC中,主要有3种类型的光标: (1) 单向光标 单向光标只能向前移动,要返回记录集的开始位置,必须先关闭光标,再打开光标,它对与只需要浏览一次的应用非常有用,而且效率很高。 (2) 可滚动光标 可滚动光标常用于基于图形用户界面的程序,用户通过(tnggu)屏幕向前或向后滚动,浏览记录集中的数据。 (3) 块光标(un bio) 所谓块光标,可以(ky)理解为执行多行的光标,他所指向的行称为行集。对于网络环境下的应用,使用块光标可以在一定程

54、度上减轻网络负载。 要使用块光标,应完成以下工作: 设定行集大小 绑定行集缓冲区 设定语句句柄属性 取行行集结果 块光标返回多行记录,应用程序必须把这多行的数据绑定到某些数据组中,这些数据组称为行集缓冲区。绑定方式有两种,列方式和行方式。 (4) ODBC光标库 有些应用程序不支持可滚动光标和块光标,ODBC SDK提供了一个光标库(ODBCCR32.DLL),在应用程序中可通过设置连接属性(SQL_STTR_ODBC_CURSORS)激活光标库。 先用函数SQLExecDirect执行SQL语句,接着用函数SQLBindCol绑定列,然后用函数SQLFetch遍历记录,获取记录的参考代码如下

55、: #define NAME_LEN 50 #define PHONE_LEN 10 SQLCHAR szNameNAME_LEN, szPhonePHONE_LEN; SQLINTEGER sCustID, cbName, cbCustID, cbPhone; SQLHSTMT hstmt; SQLRETURN retcode; /执行SQL语句retcode = SQLExecDirect(hstmt, “SELECT CUSTID, NAME, PHONE FROM CUSTOMERS ORDER BY 2,1,3”, SQL_NTS); if(retcode != SQL_SUCCES

56、S) & (retcode != SQL_SUCCESS_WITH_INFO) /执行成功 /绑定1,2,3列 SQLBindCol(hstmt, 1, SQL_C_ULONG, &sCustID, 0, &cbCustID);SQLBindCol(hstmt, 2, SQL_C_CHAR, szName, NAME_LEN, &cbName); SQLBindCol(hstmt, 3, SQL_C_CHAR, szPhone, PHONE_LEN, &cbPhone); /遍历记录集,输出结果 while(TRUE) retcode = SQLFetch(hstmt); if(retcode

57、 = SQL_ERROR | retcode = SQL_SUCCESS_WITH_INFO) /出错,输出错误,返回 show_error(); if(retcode = SQL_SUCCESS | retcode = SQL_SUCCESS_WITH_INFO) fprintf(out, “%-*s %-5d %*s”, NAME_LEN-1, szName, sCustID, PHONE_LEN-1,szPhone); else break; 记录的添加(tin ji)、删除和更新 应用程序对数据源的数据更新可以通过3种方式实现:通过SQLExecDirect函数使用相应(xingyng

58、)的SQL语句在数据源上执行,调用SQLSetPos函数实现记录集的定义更新,调用SQLBulkOperations函数实现数据的更新。 直接在数据源上执行SQL语句的方式可以适用于任何的ODBC数据源,但是,对于后两种更新(gngxn)方式,有的数据源并不支持,应用程序可以调用函数SQLGetInfo确定数据源是否支持着两种方式。 1、 直接执行SQL语句在Demo1中专门有一个函数负责执行SQL语句,其代码如下: BOOL CMyODBC:ExeSqlDirect(const char *cpSqlStmt) SQLHSTMT hstmt; if(this-m_hdbc = NULL) A

59、fxMessageBox(“没有连接数据库,请先连接!”); return FALSE; /分配连接句柄 m_retcode = SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &hStmt); if(m_retcode != SQL_SUCCESS) & (m_retcode != SQL_SUCCESS_WITH_INFO) ReportError(m_hdbc, SQL_HANDLE_DBC, “分配语句句柄失败,不能执行”); return FALSE; /直接执行SQL语句 m_retcode = SQLExecDirect(hstmt, (unsigned char *)cpSqlStmt, SQL_NTS); if(m_retco

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论