在使用C++访问数据库时一定会使用到连接与连接池,下面就以MS SQL Server为例,介绍一下如何使用它们。
目录
一、连接字符串是怎样定义的?
二、如何使用连接字符串?
三、连接中需要设置哪些属性?
四、如何获取连接的属性值?
五、如何设置连接池
六、如何从连接池中取出连接,如何释放连接池中的连接?
下面通过一个例子,说明连接字符串要如何配置:
Driver={ODBC Driver 17 for SQL Server};Address=tcp:127.0.0.1,1433;Server=\\TestServer;Database=testDB;Uid=guest;Pwd=12345678;language=Simplified Chinese;
其中Address的内容可以和到Server中。
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
SQLRETURN retcode;
# 分配环境句柄
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
# 使用环境句柄设置驱动版本号
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
# 分配连接句柄
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
# 设置连接登录超时
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
SQLWCHAR outstr[1024];
SQLSMALLINT outstrlen;
retcode = SQLDriverConnect(hdbc, NULL, (SQLWCHAR*)
L"Driver={ODBC Driver 17 for SQL Server};Server=127.0.0.1,1433\\TestServer;Database=testDB;Uid=sa;Pwd=12345678;",
SQL_NTS, outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_NOPROMPT);
SQLDriverConnect函数的定义如下:
SQLRETURN SQLDriverConnect(
SQLHDBC ConnectionHandle,
SQLHWND WindowHandle,
SQLCHAR * InConnectionString,
SQLSMALLINT StringLength1,
SQLCHAR * OutConnectionString,
SQLSMALLINT BufferLength,
SQLSMALLINT * StringLength2Ptr,
SQLUSMALLINT DriverCompletion);
InConnectionString——表示连接字符串。如果StringLength1的值为SQL_NTS,则InConnectionString必须以'\0'结尾,否则,StringLength1要指定InConnectionString的长度。
OutConnectionString——表示InConnectionString被解析完成后最终生成的连接字符串。
BufferLength——表示用于存放OutConnectionString的缓冲区大小。
StringLength2Ptr——表示最终生成的OutConnectionString的长度。
设置连接属性的函数如下:
SQLRETURN SQLSetConnectAttr(
SQLHDBC ConnectionHandle,
SQLINTEGER Attribute,
SQLPOINTER ValuePtr,
SQLINTEGER StringLength);
常用连接属性、属性类型、可选属性参数:
SQL_ATTR_CONNECTION_TIMEOUT An SQLUINTEGER value
SQL_ATTR_LOGIN_TIMEOUT An SQLUINTEGER value
SQL_ATTR_PACKET_SIZE An SQLUINTEGER value
SQL_ATTR_ACCESS_MODE An SQLUINTEGER value. if a data source is read-only or read-write.
SQL_MODE_READ_ONLY
SQL_MODE_READ_WRITE default
SQL_ATTR_AUTOCOMMIT A SQLUINTEGER value
SQL_AUTOCOMMIT_ON default
SQL_AUTOCOMMIT_OFF
SQL_ATTR_TXN_ISOLATION A 32-bit bitmask
SQL_TXN_READ_UNCOMMITTED
SQL_TXN_READ_COMMITTED
SQL_TXN_REPEATABLE_READ
SQL_TXN_SERIALIZABLE
SQL_ATTR_CONNECTION_DEAD A read-only SQLUINTEGER value
SQL_CD_TRUE
SQL_CD_FALSE
这些属性的具体说明及其它属性的说明,请查阅参考文档。
可以通过SQLGetConnectAttr 函数获取连接的属性值,下面举例说明:
SQLUINTEGER getAutoCommit(SQLHDBC hdbc) {
SQLUINTEGER autoCommit;
SQLRETURN retCode = SQLGetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)&autoCommit, sizeof(autoCommit), NULL);
return autoCommit;
};
SQLUINTEGER getTxnIsolation(SQLHDBC hdbc) {
SQLUINTEGER txnIsolation;
SQLRETURN retCode = SQLGetConnectAttr(hdbc, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)&txnIsolation, sizeof(txnIsolation), NULL);
return txnIsolation;
};
设置连接池需要用到的环境属性及其可选的值:
SQL_ATTR_CONNECTION_POOLING
SQL_CP_ONE_PER_HENV
SQL_CP_ONE_PER_DRIVER
SQL_CP_DEFAULT = SQL_CP_OFF
SQL_CP_OFF
SQL_CP_ONE_PER_HENV——表示每个环境对应一个池。这个池中可以有不同驱动的连接
SQL_CP_ONE_PER_DRIVER——表示每个驱动对应一个池。这个池中可以有从不同环境中创建的连接,只要驱动相同就会放到一个池中。
SQLHENV henv = SQL_NULL_HENV;
SQLRETURN retCode;
retCode = SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER*)SQL_CP_ONE_PER_HENV, 0);
retCode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
注意,连接池属性必须在环境句柄创建前设置。
从连接池中取出连接的方式跟创建单个连接的方式相同,都是先设置连接属性再创建连接(有些连接属性可能在创建连接后设置)
SQLHDBC hdbc = SQL_NULL_HDBC;
SQLRETURN retCode;
retCode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)5, 0);
retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_ACCESS_MODE, (SQLPOINTER)accessMode, 0);
retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)txnIsolationLevel, 0);
retCode = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)autoCommit, 0);
SQLWCHAR outConnStr[1024];
SQLSMALLINT outConnLen;
retCode = SQLDriverConnect(hdbc, NULL, (SQLWCHAR*)connStr.c_str(), SQL_NTS, outConnStr, sizeof(outConnStr), &outConnLen, SQL_DRIVER_NOPROMPT);
释放连接池中的连接跟释放单个连接使用的API相同,不同之处在于相同API背后实现的机制不同:连接池中的连接释放后会返回连接池,后续可再取出使用,而单个连接释放后是断开连接。
if (hdbc != SQL_NULL_HDBC) {
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
hdbc = SQL_NULL_HDBC;
}
参考
将连接字符串关键字用于 SQL Server Native Client
SQLDriverConnect 函数
SQLSetConnectAttr 函数
ODBC连接池配置:
Pooling in the Microsoft Data Access Components
关于连接池环境如何创建,请查阅“SQLAllocHandle 函数”
关于连接池的配置参数的介绍,请查阅“SQLSetEnvAttr 函数”