例如SQLExecute
,使用命令的命令失败后,是否可以再次使用ODBC语句句柄(即,它是否有效)?(不返回SQL_SUCCESS或SQL_SUCCESS_WITH_INFO)
并且这可能是特定于DBMS /驱动程序的吗?
我在ODBC程序员的参考页上找不到有关此的任何信息。
我也没有在文档中找到任何权威性的答案。但是我会说:是的-可以,除了返回的错误代码是SQL_INVALID_HANDLE
:
推理:
要求语句句柄作为参数的函数文档中,没有任何关于在发生错误的情况下使句柄无效的内容。重要的是返回码。因此,如果没有明确禁止它,它应该可以工作。
如果返回SQL_ERROR,则可以使用相同的语句句柄来获取有关该错误的更多信息。因此,语句句柄仍然具有有效的上下文。
3:即使在返回SQL_ERROR的情况下,我们也一次又一次使用同一条语句。到目前为止,我们没有任何问题。好吧,但是大多数情况下我们没有任何错误。
在有关“语句已终止”的注释之后更新:是的,您可以重新使用相同的语句句柄。该错误仅表示服务器正在终止当前正在运行的语句。请参见以下示例,该示例会产生这样的错误,然后再次使用相同的语句来成功插入:
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <sql.h>
#include <sqlext.h>
#include <sqlucode.h>
void printErr(SQLHANDLE handle, SQLSMALLINT handleType)
{
SQLSMALLINT recNr = 1;
SQLRETURN ret = SQL_SUCCESS;
while (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
{
SQLWCHAR errMsg[SQL_MAX_MESSAGE_LENGTH + 1];
SQLWCHAR sqlState[5 + 1];
errMsg[0] = 0;
SQLINTEGER nativeError;
SQLSMALLINT cb = 0;
ret = SQLGetDiagRec(handleType, handle, recNr, sqlState, &nativeError, errMsg, SQL_MAX_MESSAGE_LENGTH + 1, &cb);
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
{
std::wcerr << L"ERROR; native: " << nativeError << L"; state: " << sqlState << L"; msg: " << errMsg << std::endl;
}
++recNr;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
// connect to db
SQLRETURN nResult = 0;
SQLHANDLE handleEnv = 0;
nResult = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, (SQLHANDLE*)&handleEnv);
nResult = SQLSetEnvAttr(handleEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3_80, SQL_IS_INTEGER);
SQLHANDLE handleDBC = 0;
nResult = SQLAllocHandle(SQL_HANDLE_DBC, handleEnv, (SQLHANDLE*)&handleDBC);
SQLWCHAR strConnect[256] = L"Driver={SQL Server};Server=.\\INSTANCE;Database=Test;Trusted_Connection=yes;";
SQLWCHAR strConnectOut[1024] = { 0 };
SQLSMALLINT nNumOut = 0;
nResult = SQLDriverConnect(handleDBC, NULL, (SQLWCHAR*)strConnect, SQL_NTS, (SQLWCHAR*)strConnectOut, sizeof(strConnectOut), &nNumOut, SQL_DRIVER_NOPROMPT);
if (!SQL_SUCCEEDED(nResult))
printErr(handleDBC, SQL_HANDLE_DBC);
SQLHSTMT handleStatement = SQL_NULL_HSTMT;
nResult = SQLAllocHandle(SQL_HANDLE_STMT, handleDBC, (SQLHANDLE*)&handleStatement);
if (!SQL_SUCCEEDED(nResult))
printErr(handleDBC, SQL_HANDLE_DBC);
// try to drop table Wallet, ignore if it exists
nResult = SQLExecDirect(handleStatement, L"DROP TABLE Wallet", SQL_NTS);
// create table Wallet
nResult = SQLExecDirect(handleStatement, L"CREATE TABLE Wallet (WalletID int NOT NULL, Name nvarchar(5) NOT NULL)", SQL_NTS);
if (!SQL_SUCCEEDED(nResult))
printErr(handleStatement, SQL_HANDLE_STMT);
// Create a query that fails with data truncation and statement got terminated error:
nResult = SQLExecDirect(handleStatement, L"INSERT INTO Wallet (WalletID, Name) VALUES (1, 'SomethingTooLong')", SQL_NTS);
if (!SQL_SUCCEEDED(nResult))
printErr(handleStatement, SQL_HANDLE_STMT);
// and now run a query on the same statement and check in the db: Has been inserted just fine
nResult = SQLExecDirect(handleStatement, L"INSERT INTO Wallet (WalletID, Name) VALUES (2, 'Fan')", SQL_NTS);
if (!SQL_SUCCEEDED(nResult))
printErr(handleStatement, SQL_HANDLE_STMT);
// actually we should now free all handles properly...
return 0;
}
该程序的输出为:
错误; 母语:8152; 状态:22001;msg:[Microsoft] [ODBC SQL Server驱动程序] [SQL Server]字符串或二进制数据将被截断。错误; 本地人:3621; 状态:01000;msg:[Microsoft] [ODBC SQL Server驱动程序] [SQL Server]该语句已终止。
但是,使用该语句成功执行的最后一个没有错误的插入查询已成功执行:检入数据库,查看是否已插入行(并且SQLExecDirect没有返回任何错误)。
有关SQL_INVALID_HANDLE的信息,请参见此处:https ://msdn.microsoft.com/zh-cn/library/ms716219( v= vs.85).aspx
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句