一致性
引入的版本:ODBC 1.0 标准符合性:ISO 92
总结
SQLConnect 建立与驱动程序和数据源的连接。 连接处理指涉到数据源的所有连接信息,包括状态、事务状态和错误信息。
Syntax
SQLRETURN SQLConnect(
SQLHDBC ConnectionHandle,
SQLCHAR * ServerName,
SQLSMALLINT NameLength1,
SQLCHAR * UserName,
SQLSMALLINT NameLength2,
SQLCHAR * Authentication,
SQLSMALLINT NameLength3);
Arguments
ConnectionHandle
[输入] 连接句柄。
ServerName
[输入]数据源名称。 数据可能位于程序所在的同一台计算机上,或者位于网络上的某个位置的另一台计算机上。 有关应用程序如何选择数据源的信息,请参见 “选择数据源或驱动程序”。
NameLength1
[输入]*ServerName 字符长度。
UserName
[输入]用户标识。
NameLength2
[输入]*用户名 字符数长度。
Authentication
[输入]认证字符串(通常是密码)。
NameLength3
[输入]*以字符为单位的认证 时长。
Returns
SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_ERROR、SQL_INVALID_HANDLE或SQL_STILL_EXECUTING。
Diagnostics
当 SQLConnect 返回 SQL_ERROR 或 SQL_SUCCESS_WITH_INFO 时,可以通过调用 SQLGetDiagRec 的 HandleType 为 SQL_HANDLE_DBC 和 Handle 为ConnectionHandle 来获得相应的 SQLSTATE 值。 下表列出了 SQLConnect 通常返回的SQLSTATE值,并在此函数的上下文中解释了每个值;“(DM)” 符号位于驱动程序管理器返回的 SQLSTATE 描述之前。 除非另有说明,否则与每个 SQLSTATE 值关联的返回代码SQL_ERROR。
| SQLSTATE | Error | Description |
|---|---|---|
| 01000 | 常规警告 | 特定于驱动程序的信息性消息。 (函数返回SQL_SUCCESS_WITH_INFO。) |
| 01S02 | 选项值已更改 | 驱动程序不支持SQLSetConnectAttr中指定的ValuePtr参数值,并用类似值替换。 (函数返回SQL_SUCCESS_WITH_INFO。) |
| 08001 | 客户端无法建立连接 | 司机无法与数据源建立连接。 |
| 08002 | 连接名称的使用情况 | (DM) 指定的 连接句柄 已被用于与数据源建立连接,且连接仍然开放,或者用户正在浏览连接。 |
| 08004 | 服务器拒绝了连接 | 数据源因实施定义的原因拒绝了该连接的建立。 |
| 08S01 | 通信链接失败 | 驱动程序与驱动试图连接的数据源之间的通信链路在函数完成处理前就已失效。 |
| 28000 | 无效授权规范 | 参数 UserName 指定的值或参数 Authentication 指定的值违反了数据源定义的限制。 |
| HY000 | 常规错误 | 发生错误:没有特定的 SQLSTATE,也没有定义特定于实现的 SQLSTATE。 *MessageText 缓冲区中 SQLGetDiagRec 返回的错误消息描述错误及其原因。 |
| HY001 | 内存分配错误 | (DM) 驱动程序管理器无法分配支持执行或完成该函数所需的内存。 |
| HY008 | 操作已取消 |
ConnectionHandle 启用了异步处理。 调用了 SQLConnect 函数,在执行完成前,ConnectionHandle 上调用了 SQLCancelHandle 函数,然后再次调用 SQLConnect函数。 或者,调用 了 SQLConnect 函数,在执行完成前, SQLCancelHandle 被从多线程应用中的另一个线程调用到 ConnectionHandle 上。 |
| HY010 | 函数序列错误 | (DM) 一个异步执行函数(不是这个)被调用为 ConnectionHandle 而运行,且在调用该函数时仍在执行。 |
| HY013 | 内存管理错误 | 无法处理函数调用,因为基础内存对象无法访问,可能是因为内存条件低。 |
| HY090 | 字符串或缓冲区长度无效 | (DM) 参数 NameLength1、 NameLength2或 NameLength3 指定的值小于0但不等于SQL_NTS。 (DM) 参数 NameLength1 的指定值超过了数据源名称的最大长度。 |
| HYT00 | 已超时 | 查询超时期在与数据源连接完成前已到期。 超时时间通过 SQLSetConnectAttr, SQL_ATTR_LOGIN_TIMEOUT 设定。 |
| HY114 | 驱动程序不支持连接级异步函数执行 | (DM) 应用程序在连接前启用了连接句柄的异步操作。 然而,该驱动程序不支持对连接句柄进行异步操作。 |
| HYT01 | 超过连接超时时间 | 在数据源响应请求之前,连接超时期限已过期。 连接超时期限通过 SQLSetConnectAttr 设置,SQL_ATTR_CONNECTION_TIMEOUT。 |
| IM001 | 驱动程序不支持此函数 | (DM) 数据源名称指定的驱动程序不支持该函数。 |
| IM002 | 找不到数据源,也未指定默认驱动 | (DM) 参数 ServerName 中指定的数据源名称未在系统信息中找到,也没有默认驱动规范。 |
| IM003 | 指定驱动程序无法连接到 | (DM) 系统信息中数据源规范中列出的驱动程序未被找到或因其他原因无法连接。 |
| IM004 | 驱动程序的 SQLAllocHandle 在 SQL_HANDLE_ENV 失败 | (DM) 在 SQLConnect 期间,驱动程序管理器调用了驱动程序的 SQLAllocHandle 函数, HandleType 为 SQL_HANDLE_ENV,驱动程序返回错误。 |
| IM005 | 驱动程序的 SQLAllocHandle 在 SQL_HANDLE_DBC 失败 | (DM) 在 SQLConnect 期间,驱动程序管理器调用了驱动程序的 SQLAllocHandle 函数, HandleType 为 SQL_HANDLE_DBC,驱动程序返回错误。 |
| IM006 | Driver's SQLSetConnectAttr failed | 在 SQLConnect 期间,驱动程序管理器调用了驱动程序的 SQLSetConnectAttr 函数,驱动程序返回了错误。 (函数返回SQL_SUCCESS_WITH_INFO。) |
| IM009 | 无法连接到翻译 DLL | 驱动程序无法连接到为数据源指定的翻译 DLL。 |
| IM010 | 数据源名称太长 | (DM) *ServerName 超过SQL_MAX_DSN_LENGTH字符。 |
| IM014 | 指定的DSN包含驱动程序与应用程序之间的架构不匹配 | (DM)32位应用使用连接64位驱动的DSN;反之亦然。 |
| IM015 | 驱动程序的 SQLConnect 在 SQL_HANDLE_DBC_INFO_HANDLE 上失败了 | 如果驱动程序返回SQL_ERROR,驱动程序管理器会将SQL_ERROR返回应用程序,连接将失败。 有关SQL_HANDLE_DBC_INFO_TOKEN的更多信息,请参见 《ODBC司机中 Connection-Pool 意识的培养》。 |
| IM017 | 在异步通知模式下禁用轮询 | 每当使用通知模型时,轮询将被禁用。 |
| IM018 | 尚未调用 SQLCompleteAsync 来完成此句柄上的上一个异步操作。 | 如果句柄上的上一个函数调用返回SQL_STILL_EXECUTING并且启用通知模式, 则必须在句柄上调用 SQLCompleteAsync 才能执行后期处理并完成操作。 |
| S1118 | 驱动程序不支持异步通知 | 当驱动不支持异步通知时,你无法设置SQL_ATTR_ASYNC_DBC_EVENT或SQL_ATTR_ASYNC_DBC_RETCODE_PTR。 |
注释
关于应用程序为何使用 SQLConnect 的信息,请参见 “连接 SQLConnect”。
驱动程序管理器直到应用程序调用函数(SQLConnect、 SQLDriverConnect 或 SQLBrowseConnect)来连接驱动后,才会连接到驱动程序。 在此之前,驱动管理器会使用自己的句柄并管理连接信息。 当应用程序调用连接函数时,驱动程序管理器会检查驱动程序当前是否连接到指定的 ConnectionHandle:
如果驱动程序未连接,驱动程序管理器会连接到该驱动程序,并调用 SQLAllocHandle,HandleType 为 SQL_HANDLE_ENV,SQLAllocHandle 使用 SQL_HANDLE_DBC HandleType,SQLSetConnectAttr(如果应用程序指定了任何连接属性), 以及驱动程序中的连接函数。 如果驱动程序对 SQLSetConnectAttr 出现错误,驱动程序管理器会返回 SQLSTATE IM006(驱动程序的 SQLSetConnectOption 失败)并返回连接函数的 SQL_SUCCESS_WITH_INFO。 更多信息请参见 “连接数据源或驱动程序”。
如果指定的驱动程序已经在 ConnectionHandle 上连接,驱动程序管理器只调用驱动中的连接函数。 此时,驱动程序必须确保连接 句柄 的所有连接属性保持当前设置。
如果连接了不同的驱动程序,驱动程序管理器调用带有 HandleType 为 SQL_HANDLE_DBC 的 SQLFreeHandle;如果该环境中没有其他驱动程序连接,则调用该驱动中 HandleType 为 SQL_HANDLE_ENV 的 SQLFreeHandle,然后断开该驱动程序。 然后执行与未连接驱动时相同的操作。
驱动随后分配句柄并初始化自身。
当应用程序调用 SQLDisconnect 时,驱动程序管理器会在驱动程序中调用 SQLDisconnect 。 不过,它不会断开驱动单元。 这样可以将驱动程序保留在内存中,以便反复连接和断开数据源的应用程序使用。 当应用程序调用 HandleType 为 SQL_HANDLE_DBC 的 SQLFreeHandle 时,驱动程序管理器会调用 SQLFreeHandle 的 HandleType SQL_HANDLE_DBC 然后调用驱动程序中的HandleType(SQL_HANDLE_ENV),然后断开驱动。
ODBC 应用程序可以建立多个连接。
司机经理指南
*ServerName 的内容会影响驱动程序管理器与驱动程序如何协作建立与数据源的连接。
如果 *ServerName 包含有效的数据源名称,驱动管理器会在系统信息中找到对应的数据源规范并连接到关联的驱动程序。 驱动程序管理器将每个 SQLConnect 参数传递给驱动程序。
如果找不到数据源名称或 ServerName 为空指针,驱动管理器会定位默认数据源规范并连接到关联驱动。 驱动程序管理器将未修改的用户 名 和 认证 参数传递给驱动程序,以及DEFAULT“”作为 ServerName 参数。
如果 ServerName 参数为“DEFAULT”,驱动管理器会定位默认数据源规范并连接到关联的驱动程序。 驱动程序管理器将每个 SQLConnect 参数传递给驱动程序。
如果找不到数据源名称或 ServerName 为空指针,且默认数据源规范不存在,驱动程序管理器会返回SQL_ERROR SQLSTATE IM002(未找到数据源名称且未指定默认驱动)。
驱动程序管理器连接后,驱动程序可以在系统信息中找到对应的数据源规格,并利用规范中的驱动程序特定信息完成所需的连接信息集合。
如果数据源的系统信息中指定了默认翻译库,驱动程序会连接到该库。 通过调用带有 SQL_ATTR_TRANSLATE_LIB 属性的 SQLSetConnectAttr 可以连接到另一个翻译库。 通过调用带有 SQL_ATTR_TRANSLATE_OPTION 属性的 SQLSetConnectAttr 来指定转换选项。
如果驱动程序支持 SQLConnect,驱动程序系统信息中的驱动程序关键字部分必须包含 ConnectFunctions 关键字,首个字符为“Y”。
连接池
连接池允许应用程序重用已创建的连接。 当连接池被启用并调用 SQLConnect 时,驱动程序管理器会尝试使用指定为连接池环境中的连接来建立连接。 该环境是一个共享环境,所有使用该池连接的应用程序都使用。
在环境分配之前,通过调用 SQLSetEnvAttr 将 SQL_ATTR_CONNECTION_POOLING 设置为 SQL_CP_ONE_PER_DRIVER(每个驱动最多一个池)或 SQL_CP_ONE_PER_HENV(每个环境最多一个池)来启用连接池。 此时调用 SQLSetEnvAttr 时 EnvironmentHandle 设为空,使该属性成为进程级属性。 如果SQL_ATTR_CONNECTION_POOLING设置为SQL_CP_OFF,连接池会被禁用。
在启用连接池后,调用带有 HandleType 的 SQLAllocHandle SQL_HANDLE_ENV 来分配环境。 该调用分配的环境是共享环境,因为连接池已被启用。 然而,要等调用带有 HandleType 为 SQL_HANDLE_DBC 的 SQLAllocHandle 时,才会确定所使用的环境。
调用带有 HandleType 为 SQL_HANDLE_DBC 的 SQLAllocHandle 来分配连接。 驱动程序管理器尝试寻找与应用程序设定的环境属性匹配的现有共享环境。 如果不存在这样的环境,则创建一个隐式 共享环境。 如果找到匹配的共享环境,环境句柄会返回应用程序,并增加其引用计数。
然而,要等调用 SQLConnect 后才确定所使用的连接。 此时,驱动管理器会尝试在连接池中寻找符合应用程序要求条件的现有连接。 这些条件包括调用 SQLConnect 时请求的连接选项( ServerName、 UserName 和 Authentication 关键字的值)以及自调用 SQLAllocHandle 后设置的任何连接属性, HandleType 为 SQL_HANDLE_DBC。 驱动程序管理器会将这些条件与池中连接中的对应关键词和属性进行核对。 如果找到匹配,则使用池中的连接。 如果找不到匹配,则会创建一个新的连接。
如果SQL_ATTR_CP_MATCH环境属性设置为SQL_CP_STRICT_MATCH,匹配必须精确,池中的连接才会被使用。 如果SQL_ATTR_CP_MATCH环境属性设置为SQL_CP_RELAXED_MATCH,则调用 SQLConnect 时的连接选项必须匹配,但并非所有连接属性都必须匹配。
当应用程序在调用 SQLConnect 之前设置的连接属性与池中该连接属性不匹配时,应用以下规则:
如果连接属性必须在连接建立前设置:
如果SQL_ATTR_CP_MATCH SQL_CP_STRICT_MATCH,池连接中的SQL_ATTR_PACKET_SIZE必须与应用程序设置的属性相同。 如果SQL_CP_RELAXED_MATCH,SQL_ATTR_PACKET_SIZE的数值可能会不同。
SQL_ATTR_LOGIN_VALUE的价值不会影响比赛结果。
如果连接属性可以在连接建立前或连接后设置:
如果连接属性未由应用程序设置,而是在池中该连接上设置,且存在默认值,池中连接中的连接属性会被恢复为默认值,并声明匹配。 如果没有违约,合并的连接不被视为匹配。
如果连接属性已被应用程序设置,但尚未在池中的连接上设置,则池中的连接属性会被更改为应用程序设置的属性,并声明匹配。
如果连接属性已被应用程序设置,且在池中的连接上也被设置,但值不同,则使用应用程序连接属性的值并声明匹配。
如果驱动程序特定的连接属性值不相同且SQL_ATTR_CP_MATCH设置为SQL_CP_STRICT_MATCH,则池中的连接不被使用。
当应用程序调用 SQLDisconnect 断开连接时,连接会返回到连接池,并可重复使用。
优化连接池性能
当涉及分布式事务时,可以通过使用 SQL_DTC_TRANSITION_COST(SQLUINTEGER 位掩码)来优化连接池性能。 这里提到的转移是连接属性SQL_ATTR_ENLIST_IN_DTC从值0到非零的转变,反之亦然。 这是一种连接,从未被分配式事务中登记到被分配式事务中,反之亦然。 根据驱动程序实现的注册方式(设置连接属性SQL_ATTR_ENLIST_IN_DTC),这些转换可能成本高昂,因此应避免以获得最佳性能。
驱动程序返回的值包含以下任意组合的位:
SQL_DTC_ENLIST_EXPENSIVE,当设置为时,意味着从零到非零的转换比从非零到另一个非零值的转换(将之前已加入的连接纳入下一次交易)要昂贵得多。
SQL_DTC_UNENLIST_EXPENSIVE,当设置为时,意味着非零到零的转换成本远高于使用SQL_ATTR_ENLIST_IN_DTC属性已设为零的连接。
性能和连接使用权衡存在权衡。 如果驱动程序表示其中一个或多个转换成本较高,驱动管理器的连接池程序会通过保留更多连接来响应。 池中的一些连接优先用于非事务性使用,有些则优先用于事务性使用。 然而,如果驱动显示这些转换成本不高,可以使用更少的连接,可能在非事务性和事务性之间交替使用。
不支持SQL_ATTR_ENLIST_IN_DTC的驱动程序也不需要支持SQL_DTC_TRANSITION_COST。 对于支持SQL_ATTR_ENLIST_IN_DTC但不支持SQL_DTC_TRANSITION_COST的驱动程序,假设转换成本不高,就像驱动程序返回了0(未设置位)一样。
虽然SQL_DTC_TRANSITION_COST是在ODBC 3.5中引入的,但ODBC 2.X 驱动也能支持,因为驱动程序管理器无论驱动版本如何都会查询这些信息。
代码示例
在下面的例子中,应用程序分配环境和连接句柄。 然后它连接到带有用户IDJohnS和密码Sesame的SalesOrder数据源,处理数据。 当它完成数据处理后,会断开与数据源的连接并释放句柄。
// SQLConnect_ref.cpp
// compile with: odbc32.lib
#include <windows.h>
#include <sqlext.h>
int main() {
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLRETURN retcode;
SQLCHAR * OutConnStr = (SQLCHAR * )malloc(255);
SQLSMALLINT * OutConnStrLen = (SQLSMALLINT *)malloc(255);
// Allocate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
// Set the ODBC version environment attribute
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
// Allocate connection handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
// Set login timeout to 5 seconds
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
// Connect to data source
retcode = SQLConnect(hdbc, (SQLCHAR*) "NorthWind", SQL_NTS, (SQLCHAR*) NULL, 0, NULL, 0);
// Allocate statement handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
// Process data
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}
SQLDisconnect(hdbc);
}
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
}
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
}
相关函数
| 有关信息 | 请参阅 |
|---|---|
| 分配手柄 | SQLAllocHandle 函数 |
| 发现并枚举连接数据源所需的数值 | SQLBrowseConnect 函数 |
| 断开数据源连接 | SQLDisconnect 函数 |
| 使用连接字符串或对话框连接到数据源 | SQLDriverConnect 函数 |
| 返回连接属性的设置 | SQLGetConnectAttr 函数 |
| 设置连接属性 | SQLSetConnectAttr 函数 |