S trochou pomoci od Mata jsem byl schopen zjistit, v čem je problém, ale protože to nedal formou odpovědi, budu muset odpovědět, abych to mohl sdílet pro ty, kteří mají stejný problém a také označit jako zodpovězené.
Můj problém byl tedy ten, že jsem se nemohl připojit k databázi. Jak navrhl Mat, měl bych použít rozšířené informace o chybě známé jako SQLGetDiagRec
a také opravit argumenty podle dokumentace. Chvíli mi trvalo, než jsem se naučil, jak SQLGetDiagRec
funkce funguje, ale jednou se mi podařilo převést wchar_t
na char *
Byl jsem schopen vidět chybu, kterou to generovalo.
Při pokusu o připojení se mi zobrazila chyba Data source not found and no default driver specified
. To mi poskytlo vodítko, které naznačovalo, že jsem buď napsal nesprávný připojovací řetězec, nebo že textový řetězec byl nějak špatně interpretován nebo pozměněn.
Provádím nějaké hledání na internetu dal mi nahlédnout, že řetězec byl špatně interpretován, a abych to napravil, musel jsem z něj udělat doslovný řetězec. Určitě to vyřešilo umístění L před řetězec!
retcode = SQLDriverConnect(hdbc, 0,
(SQLWCHAR*)L"DSN=TestConnection;SERVER=localhost;UID=user;PWD=password;DRIVER=MySQL Server;",
_countof(L"DSN=TestConnection;SERVER=localhost;UID=user;PWD=password;DRIVER=MySQL Server;"),
OutConnStr, 255, &OutConnStrLen, SQL_DRIVER_COMPLETE);
Zároveň jsem se naučil, jak se zbavit promptu, což bylo po opravě prvotního problému celkem snadné zjistit. Zadejte hodnotu null pro popisovač okna, nastavte dokončení ovladače na SQL_DRIVER_COMPLETE
a ujistěte se, že jste do připojovacího řetězce přidali všechny potřebné informace.
Takže další problém, který jsem měl s dotazem s SQLExecDirect
hlásil chybu s nápisem Syntax error or access violation
. Problém byl evidentně stejný jako u spojovacího řetězce. Určitě dost
retcode = SQLExecDirect(hstmt, (SQLWCHAR*)L"SELECT TEST_STRING, TEST_INTEGER, TEST_FLOAT FROM dbo.testfire", SQL_NTS);
Fungovalo jako kouzlo.
Zde je celý kód, plně funkční:
#include <iostream>
#include <windows.h>
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
#include <string>
using namespace std;
int main(){
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLRETURN retcode;
SQLWCHAR OutConnStr[255];
SQLSMALLINT OutConnStrLen;
// Allocate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
// Set the ODBC version environment attribute
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
// Allocate connection handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
// Set login timeout to 5 seconds
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
// Connect to data source
retcode = SQLDriverConnect(
hdbc,
0,
(SQLWCHAR*)L"DSN=TestConnection;SERVER=localhost;UID=root;PWD=never140;DRIVER=MySQL Server;",
_countof(L"DSN=TestConnection;SERVER=localhost;UID=root;PWD=never140;DRIVER=MySQL Server;"),
OutConnStr,
255,
&OutConnStrLen,
SQL_DRIVER_COMPLETE );
// Allocate statement handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
// Process data
retcode = SQLExecDirect(hstmt, (SQLWCHAR*)L"SELECT TEST_STRING, TEST_INTEGER, TEST_FLOAT FROM dbo.testfire", SQL_NTS);
if (retcode == SQL_SUCCESS) {
SQLINTEGER sTestInt, cbTestStr, cbTestInt, cbTestFloat, iCount = 1;
SQLFLOAT dTestFloat;
SQLCHAR szTestStr[200];
while (TRUE) {
retcode = SQLFetch(hstmt);
if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) {
cout<<"An error occurred";
}
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO){
SQLGetData(hstmt, 1, SQL_C_CHAR, szTestStr, 200, &cbTestStr);
SQLGetData(hstmt, 2, SQL_C_ULONG, &sTestInt, 0, &cbTestInt);
SQLGetData(hstmt, 3, SQL_C_DOUBLE, &dTestFloat, 0,&cbTestFloat);
/* Print the row of data */
cout<<"Row "<<iCount<<":"<<endl;
cout<<szTestStr<<endl;
cout<<sTestInt<<endl;
cout<<dTestFloat<<endl;
iCount++;
} else {
break;
}
}
}else{
cout<<"Query execution error."<<endl;
}
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
SQLDisconnect(hdbc);
}else{
cout<<"Connection error"<<endl;
}
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
}
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
system("pause");
return 0;
}
Dokazujeme, že i ta nejmenší věc může způsobit selhání všeho.
Děkuji Matovi za vaši pomoc.