ODBC函数是一些定义好的接口,有唯一的名称,所以能够在不同的数据库直接移植。ODBC应用程序通过数据源名称来找到数据源的配置信息,包括连接数据库的必要信息和数据库访问的驱动程序,不同的数据库驱动程序实现了ODBC的接口函数,因此我们能通过ODBC函数访问数据库。
访问数据库的第一步就是连接到数据库,ODBC连接到数据库有几个步骤如下。
1. 创建环境句柄,在3.0版本后所以句柄的分配都用SQLAllocHandle()函数,句柄类型为SQL_HANDLE_ENV。
2. 在环境句柄中设置使用的ODBC版本,使用SQLSetEnvAttr()函数。
3. 分配连接句柄,使用SQLAllocHandle()函数,句柄类型为SQL_HANDLE_DBC。
4. 设置连接数据库的超时时间,使用SQLSetConnectAttr()函数。
5. 连接数据库,使用SQLConnect()函数。
下面看看这些函数的原型和参数。
分配句柄函数。
SQLRETURN SQLAllocHandle(
SQLSMALLINT HandleType,
SQLHANDLE InputHandle,
SQLHANDLE * OutputHandlePtr);
先看返回值,是一个SQLRETURN类型的值,这是一个short类型的整数,所有ODBC的函数返回值都是这个类型。返回值有下面这些SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_INVALID_HANDLE或SQL_ERROR。
再看一下参数。
HandleType是一个输入参数,分配的句柄的类型。 必须是以下值之一:
SQL_HANDLE_DBC
SQL_HANDLE_DBC_INFO_TOKEN
SQL_HANDLE_DESC
SQL_HANDLE_ENV
SQL_HANDLE_STMT
InputHandle是一个输入参数,是为其上下文分配新句柄的输入句柄。 如果 handleType 为 SQL_HANDLE_ENV,则SQL_NULL_HANDLE。如果 HandleType 为 SQL_HANDLE_DBC,则必须是环境句柄,如果它是SQL_HANDLE_STMT或SQL_HANDLE_DESC,则必须是连接句柄。
OutputHandlePtr是一个输出参数,是一个指向缓冲区的指针,该缓冲区将句柄返回到新分配的数据结构。
设置环境句柄的ODBC版本函数。
SQLRETURN SQLSetEnvAttr(
SQLHENV EnvironmentHandle,
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER StringLength);
EnvironmentHandle是一个输入参数,环境句柄。
Attribute是一个输入参数,要设置的属性,在这里是SQL_ATTR_ODBC_VERSION。
ValuePtr是一个输入参数,指向要与 Attribute 关联的值的指针。这里是一个32位整数值。
StringLength是一个输入参数,如果 ValuePtr 指向字符串,则此参数应为 *ValuePtr 的长度。不是字符串则忽略。
设置连接超时函数。
SQLRETURN SQLSetConnectAttr(
SQLHDBC ConnectionHandle,
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER StringLength);
与设置环境句柄的属性函数差不多,只不过换成了连接句柄。
ConnectionHandle是一个输入参数,连接句柄。
Attribute是一个输入参数,要设置的属性,这里是SQL_ATTR_LOGIN_TIMEOUT。
ValuePtr是一个输入参数,指向要与 Attribute 关联的值的指针。这里是一个无符号整数值,表示超时时间,以秒为单位。
StringLength是一个输入参数,如果 Attribute 定义的属性是一个字符串,表示字符串长度,否则忽略。
连接数据库函数。
SQLRETURN SQLConnect(
SQLHDBC ConnectionHandle,
SQLCHAR * ServerName,
SQLSMALLINT NameLength1,
SQLCHAR * UserName,
SQLSMALLINT NameLength2,
SQLCHAR * Authentication,
SQLSMALLINT NameLength3);
ConnectionHandle是一个输入参数,连接句柄。
ServerName是一个输入参数,数据源名称,在odbc.ini中配置的数据源。
NameLength1是一个输入参数,ServerName 的长度(以字符为单位)。
UserName是一个输入参数,用户标识符,连接数据库的用户名称。
NameLength2是一个输入参数,UserName 的长度(以字符为单位)。
Authentication是一个输入参数,身份验证字符串,通常是连接数据库用户的密码。
NameLength3是一个输入参数,身份验证Authentication的长度(以字符为单位)。
看一段连接数据库的实际例子代码。
#include "stdio.h"
#include "stdlib.h"
#include "sql.h" /* 必须包含下面的三个头文件 */
#include "sqlext.h"
#include "sqltypes.h"
SQLHANDLE envh; /* environment handle */
SQLHANDLE dbch; /* connect handle */
int connect_database(char *dsn_str, char *username, char *passwd)
{
SQLRETURN rc;
/* 分配环境句柄 */
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &envh);
if (rc != SQL_SUCCESS) {
fprintf(stderr, "Allocate environment handle error.\n");
return (-1);
}
/* 设置使用的ODBC版本 */
rc = SQLSetEnvAttr(envh, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
if (rc != SQL_SUCCESS) {
fprintf(stderr, "Set ODBC version error.\n");
goto free_handle_exit;
}
/* 分配连接句柄 */
rc = SQLAllocHandle(SQL_HANDLE_DBC, envh, &dbch);
if (rc != SQL_SUCCESS) {
fprintf(stderr, "Allocate DB connection handle error.\n");
goto free_handle_exit;
}
/* 设置连接数据库的超时时间为10秒 */
rc = SQLSetConnectAttr(dbch, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)10, 0);
if (rc != SQL_SUCCESS) {
fprintf(stderr, "Set connection timeout value error.\n");
goto free_handle_exit;
}
/* 连接到数据库,dsn_str是数据源名称,username是连接用户,passwd是验证密码
* SQL_NTS表示NULL结尾的字符串,自动计算长度
*/
rc = SQLConnect(dbch, dsn_str, SQL_NTS, username, SQL_NTS, passwd, SQL_NTS);
if (rc != SQL_SUCCESS) {
fprintf(stderr, "Connect to DB error.\n");
goto free_handle_exit;
}
fprintf(stdout, "Database connection established ......\n");
return (0);
free_handle_exit:
if (dbch != NULL) {
/* 释放连接句柄 */
SQLFreeHandle(SQL_HANDLE_DBC, dbch);
}
if (envh != NULL) {
/* 释放环境句柄 */
SQLFreeHandle(SQL_HANDLE_ENV, envh);
}
return (-1);
}