Я не могу найти никаких авторитетных ответов в документе. Но я бы сказал: Да - вы можете, за исключением возвращается код ошибки SQL_INVALID_HANDLE
:
Рассуждение:
Ни один из докторов функций, которые требуют справку-ручки в качестве аргумента не говоря ничего о недействительным в случае ошибки. Все, что имеет значение, - это код возврата. Поэтому, если это явно запрещено, оно должно работать.
В случае возврата SQL_ERROR вы можете использовать один и тот же дескриптор инструкции для получения дополнительной информации об этой ошибке. Таким образом, инструкция handle имеет действительный контекст.
3: Мы используем тот же оператор снова и снова, даже в случае возврата SQL_ERROR. И пока у нас не было никаких проблем. Ну, но в основном мы не получаем никаких ошибок ..
Update, после того, как комментарий о «Заявлении был прекращен»: Да, вы можете повторно использовать тот же оператор-ручку. Ошибка просто указывает на то, что выполняемый в настоящий момент оператор был завершен сервером. См следующий пример, который производит такую ошибку, а затем использует тот же оператор снова сделать успешную вставку:
#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;
}
Вывод этой программы:
ОШИБКА; native: 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/en-us/library/ms716219(v=vs.85).aspx
Я спрашиваю, потому что с MSSQL может случиться так, что если выполнить не удается, MSSQL можно сказать, что заявление было прекращено (и, следовательно, непригодным для использования, я думаю). Вы можете, конечно, получить от него ошибки, но можете ли вы, например, выполнить его снова с разными параметрами? '[22003] (родной 8115): [Microsoft] [драйвер ODBC 11 для SQL Server] [SQL Server] Ошибка арифметического переполнения, преобразующая выражение в тип данных tinyint; [01000] (родной номер 3621): [Microsoft] [драйвер ODBC 11 для SQL Server] [SQL Server] Оператор завершен. ' – omusil