我執行一個簡單的INSERT語句與使用SQLBindParameter
功能結合一個參數(SQL_BIGINT
)任何錯誤。執行失敗,但沒有錯誤診斷。命令如下:甲骨文ODBC插入失敗沒有診斷
INSERT INTO oracle_test_table (id) VALUES (?)
如果我使用SQLGetDiagField
得到SQL_DIAG_NUMBER
(錯誤診斷數) - 這是0,並試圖檢索使用SQLGetDiagRec
沒有任何返回任何診斷。
最少例如:
#include <cstdint>
#include <cstdio>
#include <string>
#include <sql.h>
#include <sqlext.h>
/** Oracle ODBC insert fail without error diagnostic test.
* ======================================================
*
* compile with: g++ oracle_test.cpp -o oracle_test -lodbc -std=c++11
*/
// Extract error diagnostic.
void extractDiag(SQLSMALLINT handleType, SQLHANDLE& handle, std::string& s) {
SQLINTEGER i = 1;
SQLINTEGER native;
SQLCHAR state[7];
SQLCHAR text[512];
SQLSMALLINT len;
SQLRETURN ret;
while(true) {
ret = SQLGetDiagRecA(handleType, handle, i++, state, &native, text, sizeof(text), &len);
if (!SQL_SUCCEEDED(ret))
break;
s += "[";
s += reinterpret_cast<char*>(state);
s += "] (native ";
s += std::to_string(native);
s += "): ";
s += reinterpret_cast<char*>(text);
s += "; ";
}
}
// Allocate a statement handle.
int allocateStatement(SQLHDBC& dbConn, SQLHSTMT& stmt) {
SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, dbConn, &stmt);
if (!SQL_SUCCEEDED(ret)) {
std::string s("statement allocation failed: \n");
extractDiag(SQL_HANDLE_DBC, dbConn, s);
fprintf(stderr, "%s\n", s.c_str());
return 1;
}
return 0;
}
int main() {
SQLRETURN ret;
SQLHENV env;
SQLHDBC dbConn;
SQLHSTMT stmt;
// Allocate an environment handle.
ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
// Use ODBC version 3.
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*) SQL_OV_ODBC3, 0);
// Allocate a connection handle.
ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbConn);
// Set connection attributes.
SQLSetConnectAttr(dbConn, SQL_ATTR_QUIET_MODE, 0, SQL_IS_POINTER);
SQLSetConnectAttr(dbConn, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)60, SQL_IS_UINTEGER);
SQLSetConnectAttr(dbConn, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER)60, SQL_IS_UINTEGER);
// Connection string.
char connStr[] = "UID=user;PWD=pass;DRIVER={Oracle 12c ODBC driver};Dbq=192.168.15.1:1521/dbora;"; // Oracle
//char connStr[] = "UID=user;PWD=pass;DRIVER={PostgreSQL Unicode};Server=192.168.15.1;Database=dbpg;"; // PostgreSQL
//char connStr[] = "UID=user;PWD=pass;DRIVER={MySQL ODBC 5.3 Unicode Driver};Server=192.168.15.1;Database=dbmy;"; // MySQL
// Connect.
ret = SQLDriverConnectA(dbConn, 0, reinterpret_cast<SQLCHAR*>(connStr), sizeof(connStr)-1, 0, 0, 0, SQL_DRIVER_NOPROMPT);
if (!SQL_SUCCEEDED(ret)) {
std::string s("connection failed: \n");
extractDiag(SQL_HANDLE_DBC, dbConn, s);
fprintf(stderr, "%s\n", s.c_str());
return 1;
}
char dropTable[] = "DROP TABLE oracle_test_table";
char createTable[] = "CREATE TABLE oracle_test_table (id int)";
char insert[] = "INSERT INTO oracle_test_table (id) VALUES (?)";
// Drop table in case it exists.
if (allocateStatement(dbConn, stmt))
return 1;
ret = SQLExecDirectA(stmt, reinterpret_cast<SQLCHAR*>(dropTable), sizeof(dropTable)-1);
// could fail if there's no table... ignored
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
// Create new table.
if (allocateStatement(dbConn, stmt))
return 1;
ret = SQLExecDirectA(stmt, reinterpret_cast<SQLCHAR*>(createTable), sizeof(createTable)-1);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
// Allocate handle for the INSERT statement.
if (allocateStatement(dbConn, stmt))
return 1;
// Bind BIGINT parameter.
int64_t ival = 2;
ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 19, 0, &ival, sizeof(int64_t), 0);
if (!SQL_SUCCEEDED(ret)) {
fprintf(stderr, "int binding failed\n");
return 1;
}
// Execute the INSERT statement.
ret = SQLExecDirectA(stmt, reinterpret_cast<SQLCHAR*>(insert), sizeof(insert)-1);
if (!SQL_SUCCEEDED(ret)) {
fprintf(stderr, "insert failed\n");
SQLULEN diagCount = 0;
ret = SQLGetDiagField(SQL_HANDLE_STMT, stmt, 0, SQL_DIAG_NUMBER, &diagCount, SQL_IS_UINTEGER, 0);
if (!SQL_SUCCEEDED(ret))
fprintf(stderr, "failed retrieving error diagnostic count\n");
else
fprintf(stderr, "error diagnostic count: %lu\n", diagCount);
std::string s("error diagnostics:\n");
extractDiag(SQL_HANDLE_STMT, stmt, s);
fprintf(stderr, "%s\n", s.c_str());
return 1;
}
return 0;
}
其它命令,包括CREATE TABLE,DROP TABLE或直接在命令與值INSERT(而不是使用SQLBindParameter
結合)執行沒有任何問題。而錯誤診斷檢索否則工作完全正常。例如試圖除去不存在的表時,正確返回:
[42S02] (native 942): [Oracle][ODBC][Ora]ORA-00942: table or view does not exist
但在這裏,沒有獲取返回。
你們當中有誰遇到過這樣的問題,執行命令失敗,但沒有錯誤診斷可用?
我使用 「甲骨文12C ODBC驅動程序」(即時客戶端12.1.0.2.0)上的Xubuntu 16.04 64位。使用ODBC版本3。該數據庫是「Oracle數據庫12c的企業版發行12.1.0.2.0 64位」在CentOS 7
相同的代碼工作正常在PostgreSQL 9.2.15運行(驅動「的Unicode的PostgreSQL」 9.3.300),
,並與MySQL 50年5月5日(驅動程序 「MySQL的ODBC 5.3 Unicode的驅動程序」 5.3.6)。
你提交INSERT?其他自動提交設置? – jarlh
默認情況下,ODBC設置爲自動提交。如果你關閉自動提交,結果是一樣的。 – omusil
請編輯您的問題,包括其失敗的INSERT語句,它試圖在C++代碼來處理它包括的SQLBindParameter調用等感謝。 –