ODBC -

2017-12-08 17 views
0

こんにちはすべて、ODBC -

は、ODBC SQLドライバーとデータソースのものを開発する方法を学んでコツコツ、私は思わぬ障害のビットに実行しているように見えるC++でプリペアドステートメントをコーディング。私は現在、次のステートメントを使用して、データベース上のプリペアドステートメントで働いている:

英語で
select * from TEST1 where NAME = ? and LOCATION__LATITUDE__S = ? 

は、名前と緯度座標指定する-でTEST1からすべてのレコードを検索します。 ODBCTestアプリケーションで上記を行うことができるので、データソースに接続してパラメータ化されたクエリを使用してクエリを実行できます。ここでは、私は私の問題の関数のコードを持っているものです:13個の属性(3行、13列)の3つの記録:

void ExecPreparedStatement(const char* stmt) { 
    HSTMT hstmt; 
    SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); 

    RETCODE rc = SQLPrepare(hstmt, (WCHAR*)stmt, SQL_NTS); 

    SQLSMALLINT numParams; 
    rc = SQLNumParams(hstmt, &numParams); 

    WCHAR* param1 = (WCHAR*)L"Jacob"; 
    SQLFLOAT param2 = 40.0; 

    rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 80, 0, (SQLPOINTER)param1, 300, NULL); 
    rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, 0, 0, &param2, 300, NULL); 

    rc = SQLExecute(hstmt); /* <fails here> */ 

    SQLSMALLINT numCols; 
    SQLNumResultCols(hstmt, &numCols); 

    DisplayRecords(hstmt, numCols); 

    SQLFreeHandle(SQL_HANDLE_STMT, hstmt); 
} 

この私のテストアプリケーションから同じ結果を与える必要があります。代わりに、実行に失敗します。読書を容易にするために、私はRetCodeのすべての処理をコードから削除しましたが、ステートメントが完了したことをチェックし、失敗した場合は正常に処理することができます。ここで私が誤解しているものがなければなりません。また、文からのパラメータの数が0(numParams変数)であることもわかります。私はこれがExecuteコールの後に置かれるべきだと理論化していますが、私はその時点まで実行されることはないので、今すぐテストすることはできません。

アイデア?ここのレンガの壁に私の頭をぶつける。 MSDNおよびその他のオンラインソースは、この点について有益ではありません。

主な質問の明確化:誰かがなぜ実行機能が失敗しているのか分かりませんか?

ANSWERは

問題が誤用鋳造による不正なSQLがわかりました。関数にconst char *文字列を渡すのではなく、代わりにWCHAR *でキャストされた文字列を渡し、関数の中でWCHAR *を使用します。機能コードは次のようになります。TryODBC()

HSTMT hstmt; 

SQLAllocStmt(hdbc, &hstmt); 

TryODBC(hstmt, SQL_HANDLE_STMT, SQLPrepare(hstmt, stmt, SQL_NTS)); 
// Prepare passes test - we return 0. 

WCHAR* param1 = (WCHAR*)L"Jacob"; 

TryODBC(hstmt, SQL_HANDLE_STMT, 
    SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_WCHAR, 
     SQL_WVARCHAR, 80, 0, (SQLPOINTER)param1, 300, NULL) 
); 

TryODBC(hstmt, SQL_HANDLE_STMT, SQLExecute(hstmt)); 

SQLSMALLINT numCols; 
TryODBC(hstmt, SQL_HANDLE_STMT, SQLNumResultCols(hstmt, &numCols)); 
DisplayRecords(hstmt, numCols); 

SQLFreeStmt(hstmt, SQL_CLOSE); 

次のように関数である。SQLGetDiagRecの()関数の方に私を導くための@ergする

bool disconnectOnError = false; 
if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_ERROR) { 
    if (!Success(rc)) { 
     disconnectOnError = true; 
    } 
    SQLWCHAR  state[6], errorMsg[SQL_MAX_MESSAGE_LENGTH]; 
    SQLINTEGER nativeError; 
    SQLSMALLINT i = 1, msgLen; 

    while ((rc = SQLGetDiagRec(handleType, handle, i, state, 
     &nativeError, errorMsg, sizeof(errorMsg), &msgLen)) != SQL_NO_DATA) 
    { 
     ShowMessage(nativeError, errorMsg); 
     i++; 
    } 
} 
if (disconnectOnError) { 
    Disconnect(-1); 
} 

大規模な感謝。

+0

失敗した行にはどのようなエラーがありますか? 'SQLGetDiagRec'はあなたに良いヒントを与えるはずです。それ以上の場合は、https:// stackoverflowを提供してください。com/help/mcve – erg

+0

@ergこれは、感謝しました!私はSQLGetDiagRecとその使用法を知らなかったので、グーグルと実験を少し行いました。問題は、SQLがキャストの悪用とSQLWCHARの悪用によって何らかの形で不正行為を起こしていたことです。 –

答えて

0

元の質問に回答しました。

1

ワイド文字列を渡していますが、SQL_C_CHARをパラメータ型として指定していますが、これはSQL_C_WCHARである必要があります。

300あなたのBufferLengthパラメータは意味がありません。文字列引数の正しいバイト数は、param2の場合は0を渡します(BufferLengthは非文字データまたはバイナリ文字列データでは無視されます)。

そして、すべてのODBC呼び出しの後にエラーコードをチェックする必要があります。エラーの場合は、診断をダンプします。いずれか、トレース接続属性をオンにして、結果を確認します。

+0

これは質問に答えません。 CHARとWCHARの例外を除いて、それは郵便のテキストで言われていたことを無視しているか無視しています。 –