DM4 ODBC编程指南
本章结合DM4数据库的特点,比较全面的介绍ODBC的基本概念以及DM4 ODBC DRIVER的使用方法,以便用户更好地使用DM4 ODBC编写应用程序。ODBC提供给你访问不同类型的数据库的途径。结构化查询语言SQL是一种用来访问数据库的语言。通过使用ODBC,应用程序能够使用相同的源代码和各种各样的数据库交互。这使得开发者不需要以特殊的数据库管理系统DBMS为目标,或者了解不同支撑背景的数据库的详细细节,就能够开发和发布/服务器应用程序。DM4 ODBC3.0遵照Microsoft ODBC3.0设计与开发,实现了ODBC应用程序与DM4的互连接口。用户可以直接调用DM4 ODBC3.0接口函数访问DM4,也可以使用可视化编程工具如C++ Builder、PowerBuilder等利用DM4 ODBC3.0访问DM4。在DM4客户端软件过程中,如果选择了安装ODBC驱动程序的相关选项,安装工具可完成将DM4 ODBC3.0驱动程序复制到硬盘,并在Windows注册表中登记DM4ODBC驱动程序信息的工作。要进一步使用DM4 ODBC驱动程序,请阅读本章以了解ODBC数据源管理方法。1 数据类型客户程序可以通过SQLGetTypeInfo函数来DM4 ODBC3.0支持的数据类型信息。由SQLGetTypeInfo返回的数据类型是数据源所支持的数据类型,它们是预备用于DDL(DataDefinitionLanguage)语句的。调用DM4 ODBC3.0的SQLGetTypeInfo,返回支持的数据类型如表1.1如下:表1:数据类型列表类型名 类型描述char(n) 固定串长度为n的字符串,n<=8000Varchar(n) 最大字符串长度为n的可变长度字符串,n<=8000binary(n) 固定长度为n的二进制数据,n<=8000varbinary(n) 最大长度为n的可变长度二进制数据,n<=8000Image 数据类型,可变长度的二进制数据,最大长度为2G-1Text 文本数据类型,可变长度的字符数据,最大长度为2G-1Bit 单个二进制位数据Tinyint 精度为3,刻度为0的有符号精确数字,取值范围-128…127Smallint 精度为5,刻度为0的有符号精确数字,取值范围-32,768…32,767Int 精度为10,刻度为0的有符号精确数字,取值范围-2[31]…2[31]-1Bigint 精度为19,刻度为0的有符号精确数字值,取值范围-2[63]…2[63]-1Real 二进制精度为24的有符号近似数字值,取值范围0或者绝对值为:10[-38]…10[38]Float 二进制精度为53的有符号近似数字值,取值范围0或者绝对值为:10[-308]…10[308]Double 二进制精度为53的有符号近似数字值,取值范围0或者绝对值为:10[-308]…10[308]decimal(p,s) 精度为p,刻度为s的有符号精确数字值,1≤p≤53,s≤pnumeric(p,s) 精度为p,刻度为s的有符号精确数字值,1≤p≤38,s≤pMoney 精度固定为19,刻度固定为4的精确有符号数值Date 日期数据类型,年月日字段,格式与Gregorian(罗马)日历一致Time(p) 时间数据类型,时分秒字段,精度p指定了秒的精度timestamp(p) 时间戳数据类型,年月日时分秒字段,精度p指定了秒的精度intervalyear(p) 年间隔,即两个日期之间的年数字,p为时间间隔的首项字段精度(后面简称为:首精度)intervalmonth(p) 月间隔,即两个日期之间的月数字,p为时间间隔的首精度intervalyear(p)tomonth 年月间隔,即两个日期之间的年月数字,p为时间间隔的首精度intervalday(p) 日间隔,即为两个日期/时间之间的日数字,p为时间间隔的首精度intervalhour(p) 时间隔,即为两个日期/时间之间的时数字,p为时间间隔的首精度intervalminute(p) 分间隔,即为两个日期/时间之间的分数字,p为时间间隔的首精度intervalsecond(p,q) 秒间隔,即为两个日期/时间之间的秒数字,p为时间间隔的首精度,q为时间间隔秒精度intervalday(p)tohour 日时间隔,即为两个日期/时间之间的日时数字,p为时间间隔的首精度intervalday(p)to minute 日时分间隔,即为两个日期/时间之间的日时分数字,p为时间间隔的首精度Intervalday(p)tosecond(q) 日时分秒间隔,即为两个日期/时间之间的日时分秒数字,p为时间间隔的首精度,q为时间间隔秒精度Intervallhour(p)tominute 时分间隔,即为两个日期/时间之间的时分数字,p为时间间隔的首精度intervalhour(p)tosecond(q) 时分秒间隔,即为两个日期/时间之间的时分秒数字,p为时间间隔的首精度,q为时间间隔秒精度Intervalminute(p)tosecond(q) 分秒间隔,即为两个日期/时间之间的分秒间隔,p为时间间隔的首精度,q为时间间隔秒精度注:要支持interval数据类型,必须在数据源中进行设置,否则将不提供对该类数据类型的支持。2 支持的函数客户程序可以通过SQLGetFunctions函数来获取DM4 ODBC3.0支持的函数信息。由SQLGetFunctions返回的函数列表是数据源所支持的函数。以下按照类型分类列出了DM4ODBCx提供的函数。应用程序能够通过调用SQLGetFunctions来获得指定函数的支持信息。1.连接到数据源下面的函数用于连接到数据源:(1)SQLAllocHandle:分配环境、连接、语句或者描述符句柄。(2)SQLConnect:建立与驱动程序或者数据源的连接。访问数据源的连接句柄包含了包括状态、事务申明和错误信息的所有连接信息。(3)SQLDriverConnect:与SQLConnect相似,用来连接到驱动程序或者数据源。但它比SQLConnect支持数据源更多的连接信息,它提 供了一个对话框来提示用户设置所有的连接信息以及系统信息表没有定义的数据源。(4)SQLBrowseConnect:支持一种交互方法来检索或者列出连接数据源所需要的属性和属性值。每次调用函数可以获取一个连接属性字符串,当检索完所有的属性值,就建立起与数据源的连接,并且返回完整的连接字符串,否则提示缺少的连接属性信息,用户根据此信息重新输入连接属性值再次调用此函数进行连接。2.获取驱动程序和数据源信息下面的函数用来获取驱动程序和数据源信息:(1)SQLDataSources:能够被调用多次来获取应用程序使用的所有数据源的名字。(2)SQLDrivers:返回所有安装过的驱动程序清单,包括对它们的描述以及属性关键字。(3)SQLGetInfo:返回连接的驱动程序和数据源的元信息。(4)SQLGetFunctions:返回指定的驱动程序是否支持某个特定函数的信息。(5)SQLGetTypeInfo:返回指定的数据源支持的数据类型的信息。3.设置或者获取驱动程序属性下面的函数用来设置或者获取驱动程序属性:(1)SQLSetConnectAttr:设置连接属性值。(2)SQLGetConnectAttr:返回连接属性值。(3)SQLSetEnvAttr:设置环境属性值。(4)SQLGetEnvAttr:返回环境属性值。(5)SQLSetStmtAttr:设置语句属性值。(6)SQLGetStmtAttr:返回语句属性值。4.设置或者获取描述符字段下面的函数用来设置或者获取描述符字段:(1)SQLGetDescField:返回单个描述符字段的值。(2)SQLGetDescRec:返回当前描述符记录的多个字段的值。(3)SQLSetDescField:设置单个描述符字段的值。(4)SQLSetDescRec:设置描述符记录的多个字段。5.准备SQL语句下面的函数用来准备SQL语句:(1)SQLPrepare:准备要执行的SQL语句。(2)SQLBindParameter:在SQL语句中分配参数的缓冲区。(3)SQLGetCursorName:返回与语句句柄相关的游标名称。(4)SQLSetCursorName:设置与语句句柄相关的游标名称。(5)SQLSetScrollOptions:设置控制游标行为的选项。6.提交SQL请求下面的函数用来提交SQL请求:(1)SQLExecute:执行准备好的SQL语句。(2)SQLExecDirect:执行一条SQL语句。(3)SQLNativeSql:返回驱动程序对一条SQL语句的翻译。(4)SQLDescribeParam:返回对SQL语句中指定参数的描述。(5)SQLNumParams:返回SQL语句中参数的个数。(6)SQLParamData:与SQLPutData联合使用在运行时给参数赋值。(7)SQLPutData:在SQL语句运行时给部分或者全部参数赋值。7.检索结果集及其相关信息下面的函数用来检索结果集及其相关信息:(1)SQLRowCount:返回INSERT、UPDATE或者DELETE等语句影响的行数。(2)SQLNumResultCols:返回结果集中列的数目。(3)SQLDescribeCol:返回结果集中列的描述符记录。(4)SQLColAttribute:返回结果集中列的属性。(5)SQLBindCol:为结果集中的列分配缓冲区。(6)SQLFetch:在结果集中检索下一行元组。(7)SQLFetchScroll:返回指定的结果行。(8)SQLGetData:返回结果集中当前行某一列的值。(9)SQLSetPos:在取到的数据集中设置游标的位置。这个记录集中的数据能够刷新、更新或者删除。(10)SQLBulkOperations:执行块插入和块书签操作,其中包括根据书签更新、删除或者取数据。(11)SQLMoreResults:确定是否能够获得更多的结果集,如果能就执行下一个结果集的初始化操作。(12)SQLGetDiagField:返回一个字段值或者一个诊断数据记录。(13)SQLGetDiagRec:返回多个字段值或者一个诊断数据记录。8.取得数据源系统表的信息下面的函数用来取得数据源系统表的信息:(1)SQLColumnPrivileges:返回一个关于指定表的列的列表以及相关的权限信息。(2)SQLColumns:返回指定表的列信息的列表。(3)SQLForeignKeys:返回指定表的外键信息的列表。(4)SQLPrimaryKeys:返回指定表的主键信息的列表。(5)SQLProcedureColumns:返回指定存储过程的参数信息的列表。(6)SQLProcedures:返回指定数据源的存储过程信息的列表。(7)SQLSpecialColumns:返回唯一确定某一行的列的信息,或者当某一事务修改一行的时候自动更新各列的信息。(8)SQLStatistics:返回一个单表的相关统计信息和索引信息。(9)SQLTablePrivileges:返回相关各表的名称以及相关的权限信息。(10)SQLTables:返回指定数据源中表信息。9.终止语句执行下面的函数用来终止语句执行:(1)SQLFreeStmt:终止语句执行,关闭所有相关的游标,放弃没有提交的结果,选择释放与指定语句句柄相关的资源。(2)SQLCloseCursor:关闭一个打开的游标,放弃没有提交的结果。(3)SQLCancel:放弃执行一条SQL语句。(4)SQLEndTran:提交或者回滚事务。10.中断连接下面的函数处理中断连接的任务:(1)SQLDisconnect:关闭指定连接。(2)SQLFreeHandle:释放环境、连接、语句或者描述符句柄。3 建立ODBC连接1.申请环境与连接句柄客户程序要和一个远程的服务器或数据库进行通讯,必须首先和这个服务器或数据库建立连接,如何通过ODBC建立一个连接以及使用连接呢?是我们下面将要介绍的内容。为了建立一个ODBC数据源连接,需要使用到环境句柄以及连接句柄。句柄有一个层次的概念,一个连接句柄总是和一个唯一的环境句柄相联系的,所有的连接句柄必须在环境句柄释放之前释放。客户程序可以通过调用函数SQLAllocHandle来申请一个环境句柄,调用函数SQLAllocHandle时必须传入句柄选项SQL_HANDLE_ENV,当申请环境句柄成功之后,可以在此环境句柄上申请连接句柄。申请环境句柄和连接句柄的代码示范如下:#include #include #include #include /* 检测返回代码是否为成功标志,当为成功标志返回TRUE,否则返回FALSE */#define RC_SUCCESSFUL(rc) ((rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO)/* 检测返回代码是否为失败标志,当为失败标志返回TRUE,否则返回FALSE */#define RC_NOTSUCCESSFUL(rc) (!(RC_SUCCESSFUL(rc)))HENV henv; /* 环境句柄 */HDBC hdbc; /* 连接句柄 */SQLRETURN sret; /* 返回代码 */void main(void){ /* 申请一个环境句柄 */SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);/* 设置环境句柄的ODBC版本 */SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);/* 申请一个连接句柄 */SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);/* 释放连接句柄 */SQLFreeHandle(SQL_HANDLE_DBC, hdbc);/* 释放环境句柄 */SQLFreeHandle(SQL_HANDLE_ENV, henv);}2.如何与数据源进行连接ODBC的连接是从数据源开始的,数据源是ODBC对一个特定的数据库的别称。为了访问由数据源提供的数据,你的程序中必须首先建立和数据源之间的连接,在环境和连接句柄正确分配之后,才能通过这些连接管理数据访问。为了产生建立连接时必要的参数,必须完成以下的几项工作:(1)调用SQLAllocHandle申请一个环境句柄。(2)调用SQLAllocHandle申请一个连接句柄。(3)创建一个数据源DSN。(4)一个有效的用户ID。(5)一个对应于这个用户ID的口令。(6)其它的一些提供给驱动程序的参数信息。连接ODBC数据源时,ODBC提供三种不同的连接函数,即SQLConnect、SQLDriverConnect和SQLBrowseConnect,每个函数都有不同的参数以及不同级别的一致性。表1:连接到数据源的ODBC函数函数 ODBC版本 一致性 主要参数SQLConnect 1.0 核心级 hdbc,数据源,用户ID,口令SQLDriverConnect 1.0 1级 hdbc,窗口句柄,输入连接字符串SQLBrowseConnect 1.0 2级 hdbc,输入连接字符串,连接字符串SQLConnect是连接ODBC数据源的最基本的方法,在所有的一致性级别上都支持。SQLConnect函数有以下参数:连接句柄,数据源名称,数据源名称长度,用户名(用户ID),用户名长度,用户口令以及口令长度。返回代码有:SQL_SUCCESS,SQL_SUCCESS_WITH_INFO,SQL_ERROR或者SQL_INVALID_HANDLE。使用SQLConnect函数连接数据源的代码示范如下:sret = SQLConnect(hdbc, (SQLCHAR *)"DM4", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS);if (RC_SUCCESSFUL(sret)) { /* 连接数据源失败! */…进行相应的错误处理…exit(0);}SQLDriverConnect提供了比SQLConnect更的方法来建立ODBC连接。它支持:要求更多连接参数的数据源;对话框提示用户输入所有的连接信息;以及没有在系统信息表中定义的数据源。SQLDriverConnect提供以下的连接方法:(1)用一个连接字符串建立一个连接,这个字符串包括建立连接的所有数据,如DSN,一个或多个用户ID及其口令,以及其他的数据库所需要的连接信息。(2)用一个并不完整的连接字符串来建立连接,使得ODBC驱动程序管理器来提示用户输入所需要的连接信息。(3)用一个没有在系统信息表中登记的数据源建立连接,驱动程序自动提示用户输入连接信息。(4)用一个连接字符串建立连接,这个字符串在DSN配置文件中是确定的。SQLDriverConnect函数fDriverCompletion参数说明:(1)SQL_DRIVER_PROMPT:设置此选项用来显示一个对话框来提示用户输入连接信息。(2)SQL_DRIVER_COMPLETE:如果函数调用中包含了足够的信息,ODBC就进行连接,否则弹出对话框提示用户输入连接信息,此时等同于SQL_DRIVER_PROMPT。(3)SQL_DRIVER_COMPLETE_REQUIRED:这个参数与SQL_DRIVER_COMPLETE参数唯一的不同是用户不能改变由函数提供的信息。(4)SQL_DRIVER_NOPROMPT:如果函数调用时有足够的信息,ODBC就进行连接,否则返回SQL_ERROR。使用SQLDriverConnect连接数据源的代码示范如下:SQLCHAR szConnStrIn[256] = "DSN=DM4;DRIVER=DM ODBC DRIVER;DATABASE=SYSTEM;UID=SYSDBA;PWD=SYSDBA";SQLCHAR szConnStrOut[256];SQLSMALLINT cbConnStrOut;sret = SQLDriverConnect(hdbc, hwnd, szConnStrIn, SQL_NTS, szConnStrOut, 256, &cbConnStrOut, SQL_DRIVER_PROMT);if (RC_SUCCESSFUL(sret)) { /* 连接数据源失败! */…进行相应的错误处理…exit(0);}SQLBrowseConnect函数与SQLDriverConnect函数相似,但是调用SQLBrowseConnect函数时,程序在运行时可以再形成一个连接字符串,使用这个函数可以用一个交互的方式来决定连接到数据源时所需要的一些信息。使用SQLBrowseConnect函数连接数据源的代码示范如下:SQLCHAR szConnStrIn[256] = "DSN=DM4;DRIVER=DM ODBC DRIVER;DATABASE=SYSTEM;UID=SYSDBA;PWD=SYSDBA;";SQLCHAR szConnStrOut[256];SQLSMALLINT cbConnStrOut;sret = SQLBrowseConnect(hdbc, szConnStrIn, SQL_NTS, szConnStrOut, 256, &cbConnStrOut);if (RC_SUCCESSFUL(sret)) { /* 连接数据源失败! */…进行相应的错误处理…exit(0);}3.设置与取得连接的属性建立连接之后,应用程序可以通过调用SQLSetConnectAttr函数来设置连接属性,对连接进行全方面的管理。下面列出了一些常用的连接属性。表2:常用的连接属性属性 描述SQL_ATTR_ACCESS_MODE 用来设置访问模式,即只读或者读写连接模式,可以用来优化并发控制策略。不支持SQL_ATTR_ASYNC_ENABLE 是否支持异步执行SQL_ATTR_AUTOCOMMIT 是否使用自动提交功能。SQL_ATTR_CONNECTION_TIMEOUT 设定连接超时。(不支持)SQL_ATTR_CURRENT_CATALOG 当前连接使用的编目。SQL_ATTR_LOGIN_TIMEOUT 设定登录超时。不支持SQL_ATTR_ODBC_CURSORS 设置驱动程序管理器使用游标的方式。SQL_ATTR_PACKET_SIZE 设置网络传输包的大小。不支持SQL_ATTR_QUIET_MODE 使弹出对话框有效/无效。更多的连接属性,用户可以参考《Microsoft ODBC3.0参考手册》,在这里不做介绍了。应用程序可以通过调用SQLGetConnectAttr函数来取得当前连接的属性。设置与取得连接属性的代码示范如下:SQLINTEGER AUTOCOMMIOT_MODE;/* 设置连接句柄属性,关闭自动提交功能 */SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF,SQL_IS_INTEGER);/* 取得连接句柄属性,取得提交的模式 */SQLGetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)&AUTOCOMMIOT_MODE,Sizeof(SQLINTEGER), NULL); 4.断开与数据源之间的连接如果要终止客户程序与服务器之间的连接,客户程序应当完成以下的几个操作:(1)调用SQLFreeHandle释放语句句柄,关闭所有打开的游标,释放相关的语句句柄资源。(在非自动提交模式下,需事先提交当前的事务)(2)调用函数SQLDisconnect关闭所有的连接。(3)调用SQLFreeHandle释放连接句柄及其相关的资源。(4)调用SQLFreeHandle释放环境句柄及其相关的资源。一个完整的连接管理示范代码如下:#include #include #include #include /* 检测返回代码是否为成功标志,当为成功标志返回TRUE,否则返回FALSE */#define RC_SUCCESSFUL(rc) ((rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO)/* 检测返回代码是否为失败标志,当为失败标志返回TRUE,否则返回FALSE */#define RC_NOTSUCCESSFUL(rc) (!(RC_SUCCESSFUL(rc)))HENV henv; /* 环境句柄 */HDBC hdbc; /* 连接句柄 */HSTMT hsmt; /* 语句句柄 */SQLRETURN sret; /* 返回代码 */SQLINTEGER AUTOCOMMIOT_MODE;void main(void){ /* 申请一个环境句柄 */SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);/* 设置环境句柄的ODBC版本 */SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);/* 申请一个连接句柄 */SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);sret = SQLConnect(hdbc, (SQLCHAR *)"DM4", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS);if (RC_SUCCESSFUL(sret)) { /* 连接数据源失败! */SQLFreeHandle(SQL_HANDLE_DBC, hdbc);SQLFreeHandle(SQL_HANDLE_ENV, henv);exit(0);}/* 设置连接句柄属性,关闭自动提交功能 */SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF,SQL_IS_INTEGER);/* 取得连接句柄属性,取得提交的模式 */SQLGetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)&AUTOCOMMIOT_MODE, sizeof(SQLINTEGER), NULL);/* 申请一个语句句柄 */SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hsmt);…在这里可以使用语句句柄进行相应的数据库操作…/* 释放语句句柄 */SQLFreeHandle(SQL_HANDLE_STMT, hsmt);/* 提交连接上的事务 */SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);/* 断开与数据源之间的连接 */SQLDisconnect(hdbc);/* 释放连接句柄 */SQLFreeHandle(SQL_HANDLE_DBC, hdbc);/* 释放环境句柄 */SQLFreeHandle(SQL_HANDLE_ENV, henv);}4 ODBC应用程序编程的基本步骤4.1 创建ODBC资源在客户使用ODBC方法访问一个DM4数据库服务器之前,必须先对自己的应用程序所用的ODBC资源进行配置。本节将介绍如何为你的应用程序安装和配置ODBC资源。在客户机上配置ODBC资源的步骤:1.在控制面板上访问ODBC构件,显示ODBC数据源管理器对话框,如图4.1所示。ODBC数据源管理器对话框包含的标签如下:(1)用户DSN:添加、删除或配置本机上的数据源,它们只可由当前用户使用。(2)系统DSN:添加、删除或配置本机上的数据源,它们可由任何用户使用。(3)文件DSN:添加、删除或配置在分离文件中的数据源。这些文件可以被安装了同样数据库驱动器的用户共享。(4)驱动程序:列出了安装在客户机上的数据库驱动器。(5)跟踪:用于测试你的数据库应用程序。它跟踪客户机和数据库服务器之间的ODBCAPI的调用。(6)连接池:允许不同的应用程序自动复用多个连接。这有助于限制和数据库服务器的通信过载。(7)关于:显示主要ODBC组件的版本。图4.1ODBC数据源管理器对话框2.设置和配置一个系统DSN,请单击系统DSN标签,单击添加按钮增加一个新的DSN,显示如图4.2所示的对话框。图4.2创建新数据源对话框3.选择DM4 ODBC3.0驱动程序即DMODBCDRIVER,单击完成按钮,显示如图4.3所示的DM4 ODBC3.0数据源配置对话框。图4.3创建新的DM4数据源对话框4.输入数据源的名称,一个简单的描述,并选择你想要连接的数据库服务器的名字,使用的端口号,缺省使用的DB,验证登录用户ID真伪的方式,如果使用DMServer验证方式则需要输入登录数据源的ID以及密码等信息,选择系统提示信息的语种,以及选择是否使用DMServer的增强选项。5.单击测试按钮测试你配置的数据源是否正确,得到数据源测试报告如图4.4所示,如果测试成功,可以单击确定按钮以保存你设置的新的系统数据源,如图4.5所示。图4.4数据源测试报告图4.5完成系统数据源的设置6.单击确定按钮关闭ODBC数据源管理器对话框。4.2 ODBC应用程序编写的基本步骤应用程序使用ODBC访问数据源,可以按照以下几个基本步骤进行:1.调用函数SQLAllocHandle申请环境、连接句柄,调用函数SQLSetEnvAttr设置环境句柄属性,调用函数SQLSetConnectAttr设置连接句柄属性,调用连接函数SQLConnect、SQLDriverConnect或SQLBrowseConnect连接相关的数据源。2.调用函数SQLAllocHandle申请语句句柄,通过语句句柄应用程序可以执行SQL语句进行相关的SQL操作。调用函数SQLPrepare对SQL语句和操作进行准备,调用SQLDescribeCol、SQLDescribeParam等函数取得相关的描述信息,依据描述信息调用SQLBindCol、SQLBindParam等函数绑定相关的列和参数,然后调用SQLExecute执行SQL语句,实现相关的SQL操作。应用程序也可以调用函数SQLExecDirect直接执行SQL语句进行相关的SQL操作。3.应用程序可以通过调用ODBC编目函数SQLTables、SQLColumns、SQLStatistics等取得数据源相关的字典信息。4.如果连接属性自动提交选项设置为手动提交状态,应用程序可以调用函数SQLEndTran来提交或回滚事务,进行相关的事务处理。5.调用函数SQLFreeHandle来释放申请的语句句柄。6.调用函数SQLDisconnect来断开应用程序与数据源之间的连接。7.调用函数SQLFreeHandle来释放申请的连接、环境句柄。使用ODBC编程的基本步骤如图4.6所示。图4.6直接使用ODBC函数开发应用程序的基本步骤下面是一个调用DM4 ODBC3.0的简单实例:#include #include #include #include #include /* 检测返回代码是否为成功标志,当为成功标志返回TRUE,否则返回FALSE */#define RC_SUCCESSFUL(rc) ((rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO)/* 检测返回代码是否为失败标志,当为失败标志返回TRUE,否则返回FALSE */#define RC_NOTSUCCESSFUL(rc) (!(RC_SUCCESSFUL(rc)))HENV henv; /* 环境句柄 */HDBC hdbc; /* 连接句柄 */HSTMT hsmt; /* 语句句柄 */SQLRETURN sret; /* 返回代码 */char szcode[6]; /* 厂商编号 */long cbcode = 0;char szname[21]; /* 厂商名 */long cbname = 0;char szasset[13]; /* 资产总值 */long cbasset = 0;char szaddress[11];/* 厂商地址 */long cbaddress = 0;void main(void){ /* 申请一个环境句柄 */SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);/* 设置环境句柄的ODBC版本 */SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);/* 申请一个连接句柄 */SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);SQLConnect(hdbc, (SQLCHAR *)"DM4", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS);/* 申请一个语句句柄 */SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hsmt);/* 立即执行查询厂商登记表的语句 */SQLExecDirect(hsmt, (SQLCHAR *)"SELECT 厂商编号, 厂商名, 资产总值, 厂商地址 FROM 厂商登记;", SQL_NTS);/* 绑定数据缓冲区 */SQLBindCol(hsmt, 1, SQL_C_CHAR, szcode, sizeof(szcode), &cbcode);SQLBindCol(hsmt, 2, SQL_C_CHAR, szname, sizeof(szname), &cbname);SQLBindCol(hsmt, 3, SQL_C_CHAR, szasset, sizeof(szasset), &cbasset);SQLBindCol(hsmt, 4, SQL_C_CHAR, szaddress, sizeof(szaddress), &cbaddress);/* 取得数据并且打印数据 */printf("厂商编号 厂商名 资产总值 厂商地址/n");for (;;) { sret = SQLFetchScroll(hsmt, SQL_FETCH_NEXT, 0);if (sret == SQL_NO_DATA_FOUND)break;printf("%s %s %s %s/n", szcode, szname, szasset, szaddress);}/* 释放语句句柄 */SQLFreeHandle(SQL_HANDLE_STMT, hsmt);/* 断开与数据源之间的连接 */SQLDisconnect(hdbc);/* 释放连接句柄 */SQLFreeHandle(SQL_HANDLE_DBC, hdbc);/* 释放环境句柄 */SQLFreeHandle(SQL_HANDLE_ENV, henv);}4.3 在C++Builder中通过ODBC访问DM4C++ Builder是由目前比较的数据库应用程序开发工具,能够通过ODBC进行可视化的数据库编程,下面通过一个实例简单的介绍一下如何使用C++ Builder进行可视化的数据库应用编程。首先启动DM4服务器,创建一个名为DM4的ODBC数据源,启动C++ Builder5.0集成开发环境,如图4.7所示。图4.7C++Builder集成开发环境如图4.8所示,在Form1窗体中添加TTable、TDataSource、TDBGrid、TDBNavigator组件Table1、DataSource1、DBGrid1、DBNavigator1。图4.8添加Table、DataSource等控件选中Table1,设置属性DatabaseName为DM4,设置属性TableName为厂商登记,置属性Active为TRUE。选中DataSource1,设置属性DataSet为Table1。选中DBGrid1,设置属性DataSource为DataSource1。选中DBNavigator1,设置属性DataSource为DataSource1。得到结果如图4.9所示。图4.9C++Builder可视化编程运行命令,得到的运行结果如图4.10所示。图4.10C++Builder编程实例运行结果用C++ Builder开发工具可以开发各种各样的数据库应用系统,大大地简化了数据库应用系统的开发,界面美观,开发成本低,周期短,这些应用系统已经被广泛地应用于诸如金融、消防、医院、地理、天文等等大型综合数据服务系统中。而这一切正因为ODBC,学习与掌握好ODBC,对于数据库应用系统的开发可以起到很好的帮助作用。如何使用C++ Builder进行更广泛深入的数据库编程不在本手册的谈论范围之内,读者感兴趣可参考C++ Builder编程指南。4.4 在PowerBuilder中通过ODBC访问DM4PowerBuilder也是目前广泛使用的数据库应用系统主流开发工具,下面我们通过图例介绍如何在PowerBuilder中通过ODBC访问DM4数据库管理系统。运行PowerBuilder8.0,其集成开发环境界面如图4.11所示。图4.11PowerBuilder集成开发环境点击DBProfile命令,得到如图4.12所示的对话框。图4.12DBProfile对话框选中ODBODBC,点击New按钮,如图4.13所示进行ODBCDBProfile的配置。图4.13DBProfile配置点击OK按钮,创建DM4DBProfile成功,如图4.14所示。图4.14DBProfile配置成功选中DM4,点击Connect按钮,点击Database命令,得到如图4.15所示的界面。图4.15连接DM4数据源成功客户就可以对DM4数据库进行访问了,如访问商场登记表,如图4.16所示。图4.16浏览DM4数据源中的表数据也可以浏览数据库的一些元信息,如图4.17所示。图4.17浏览数据库元信息这里简要介绍了在PowerBuilder中如何通过ODBC访问DM4数据库。PowerBuilder同样也是一个功能十分强大的数据库可视化开发工具,掌握它对设计与开发应用系统有着十分重要的帮助。读者如果感兴趣,可以参考PowerBuilder开发指南。5 使用存储过程和函数DM4允许用户创建和使用存储模块,下面介绍如何在DM4ODBC应用中使用存储过程和函数。5.1 存储过程与函数字典信息的获取DM4 ODBC3.0支持字典函数SQLProcedures的调用,用户可以调用此函数来获取DM4存储过程与函数的字典信息。调用方法如下:SQLProcedures(stmt,“SYSTEM”,SQL_NTS,“SYSDBA”,SQL_NTS,“TEST_PROC”,SQL_NTS);返回字典信息格式如表5.1。表5.1:字典信息说明表编号 字典项 相关说明1 PROCEDURE_CAT 存储模块编目信息2 PROCEDURE_SCHEM 存储模块模式信息3 PROCEDURE_NAME 存储模块名4 NUM_INPUT_PARAMS DM4暂时没有返回此项信息5 NUM_OUTPUT_PARAMS DM4暂时没有返回此项信息6 NUM_RESULT_SETS DM4暂时没有返回此项信息7 REMARKS DM4暂时没有返回此项信息8 PROCEDURE_TYPE 存储模块的类型DM4 ODBC3.0支持字典函数SQLProcedureColums的调用,用于返回存储模块的参数信息。调用方法如下:SQLProcedureColumns(stmt,“SYSTEM”,SQL_NTS,“SYSDBA”,SQL_NTS,“TEST_PROC”,SQL_NTS,NULL,0);返回字典信息格式如表5.2。表5.2:字典信息说明表编号 字典项 相关说明1 PROCEDURE_CAT 存储模块编目信息2 PROCEDURE_SCHEM 存储模块模式信息3 PROCEDURE_NAME 存储模块名4 COLUMN_NAME 参数名5 COLUMN_TYPE 参数的类型,即为输入参数还是输出参数6 DATA_TYPE 参数的SQL数据类型7 TYPE_NAME 参数的类型名8 COLUMN_SIZE 参数的精度9 BUFFER_LENGTH 参数所占用的字符长度10 DECIMAL_DIGITS 参数的刻度11 NUM_PREC_RADIX 仅对数值类型有效,仅为10或者2,如果为10表示为精确数字,如果为2表示为非精确数字12 NULLABLE 参数是否接收空值标志13 REMARK 参数说明14 COLUMN_DEF 参数的缺省值15 SQL_DATA_TYPE 参数的SQL数据类型16 SQL_DATETIME_SUB 日期时间类型或者时间间隔类型的子代码17 CHAR_OCTET_LENGTH 字符数据类型以字节计算的最大长度,非字符类型返回空值18 ORDINAL_POSITION 参数的顺序19 IS_NULLABLE 参数是否包含空值5.2 存储模块的创建用户可以使用SQLExecDirect函数执行创建存储模块的SQL语句来创建存储模块,如下例所示:SQLExecDirect(stmt, (SQLCHAR *)“create or replace procedure test_proc (c1 in int) ”“as ”“declare c2 int ”“begin ”“c2 := c1 + 100 ”“end;”, SQL_NTS);5.3 存储模块的调用调用存储模块的方法可以分为两种情况。1.立即调用如果存储过程需要设置参数,那么在调用存储模块的时候就已经为为所有的IN、INOUT类型的参数进行了赋值,带有OUT属性的参数的值是通过取得存储过程结果集的方法获取的。立即执行存储过程的示例如下:SQLExecDirect(stmt,(SQLCHAR*)”calltest_proc(123);”,SQL_NTS);2.参数调用这种调用方法指的是在调用模块的时候,其参数值用问号来代替,发送给服务器之后,服务器返回参数的准备信息,用户依据服务器返回的参数描述信息进行参数绑定,然后执行,其参数的处理方法与普通的参数处理方法相同。DM4支持存储模块返回多个结果集的处理,多结果集的切换通过SQLMoreResult函数切换,下面通过一个实例来说明如何使用。#include #include #include #include #include HENV env;HDBC dbc;HSTMT stmt;RETCODE ret;short i;short cols;char colname[129];char coldata[256];void main(void){ SQLAllocHandle(SQL_HANDLE_ENV, NULL, &env);SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);SQLConnect(dbc, (SQLCHAR *)"DM4", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS, (SQLCHAR *)"SYSDBA", SQL_NTS);SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);SQLExecDirect(stmt, (SQLCHAR *)"drop table test_table1;", SQL_NTS);SQLExecDirect(stmt, (SQLCHAR *)"drop table test_table2;", SQL_NTS);SQLExecDirect(stmt, (SQLCHAR *)"create table test_table1 (t1col int);", SQL_NTS);SQLExecDirect(stmt, (SQLCHAR *)"insert into test_table1 values(100);", SQL_NTS);SQLExecDirect(stmt, (SQLCHAR *)"create table test_table2 (t2col varchar(10));", SQL_NTS);SQLExecDirect(stmt, (SQLCHAR *)"insert into test_table2 values('hello!');", SQL_NTS);SQLExecDirect(stmt, (SQLCHAR *)"create or replace procedure test_proc as begin select * from test_table1 select * from test_table2 end;", SQL_NTS); SQLExecDirect(stmt, (SQLCHAR *)"call test_proc;", SQL_NTS);SQLNumResultCols(stmt, &cols);for (i=1; i<=cols; i++){ SQLDescribeCol(stmt, i, (SQLCHAR *)colname, 129, NULL, NULL, NULL, NULL, NULL);printf("%s ", colname);}printf("/n");for ( ; ; ){ ret = SQLFetch(stmt);if (ret == SQL_NO_DATA_FOUND) break;for (i=1; i<=cols; i++){ SQLGetData(stmt, i, SQL_C_CHAR, coldata, 256, NULL);printf("%s ", coldata);}printf("/n");} SQLMoreResults(stmt);SQLNumResultCols(stmt, &cols);for (i=1; i<=cols; i++){ SQLDescribeCol(stmt, i, (SQLCHAR *)colname, 129, NULL, NULL, NULL, NULL, NULL);printf("%s ", colname);}printf("/n");for ( ; ; ){ ret = SQLFetch(stmt);if (ret == SQL_NO_DATA_FOUND) break;for (i=1; i<=cols; i++){ SQLGetData(stmt, i, SQL_C_CHAR, coldata, 256, NULL);printf("%s ", coldata);}printf("/n");} SQLFreeHandle(SQL_HANDLE_STMT, stmt);SQLDisconnect(dbc);SQLFreeHandle(SQL_HANDLE_DBC, dbc);SQLFreeHandle(SQL_HANDLE_ENV, env);}6 多字符多语言的支持实现多字符集/多语言的支持需要客户端和服务器的协调工作。DM4服务器能够以多种字符集来存储数据,为了能够把数据库中的数据以正确的方式显示出来,还需要客户端使用适当的字符集。如果不指定字符集,那么服务器和客户端都自动采用系统默认的字符集。DM4 ODBC3.0扩充了标准函数SQLSetConnectAttr的参数值,提供了设置客户端字符集的方法,用户利用这些函数设置客户端的字符集之后,就由DM4 ODBC3.0自动实现其与服务器所采用的字符集之间的转换。调用示例如下:SQLSetConnectAttr(dbc, 123456, (SQLPOINTER)0, SQL_IS_INTEGER);在调用DM4 ODBC3.0函数SQLSetConnectAttr时,第二个参数值取123456表示设置字符集,第三个参数的取值参见表6.1。DM4现在支持的编码方式以及所对应的编码代号如表所示:表6.1:编码方式及编码代号表宏定义 编码取值PG_INVALID_CODE 0PG_UTF8 1PG_GBK 2PG_BIG5 3PG_ISO_8859_9 4PG_EUC_JP 5PG_EUC_KR 6PG_KOI8R 7PG_ISO_8859_1 8在设置字符集时,要考虑字符之间的兼容性。目前,支持国际化的应用程序大多采用Unicode编码。Unicode标准为全球商业领域中广泛使用的大部分字符定义了一个单一编码方案,不用担心系统是否会错误地翻译位模式。UTF-8是目前应用最广泛的Unicode编码方式,推荐用户采用这种编码方式。