Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Łączenie się z serwerem MySQL za pomocą C++

Z niewielką pomocą Mata udało mi się ustalić, na czym polega problem, ale ponieważ nie udzielił tego w formie odpowiedzi, będę musiał odpowiedzieć na to, aby można było się nim podzielić dla tych, którzy mają ten sam problem, a także oznaczyć jako odpowiedź.

Mój problem polegał na tym, że nie mogłem połączyć się z bazą danych. Jak zasugerował Mat, powinienem użyć rozszerzonej informacji o błędzie, znanej jako SQLGetDiagRec a także naprawić argumenty zgodnie z dokumentacją. Zajęło mi chwilę, aby dowiedzieć się, jak SQLGetDiagRec funkcja działa, ale raz udało mi się przekonwertować wchar_t na char * Byłem w stanie zobaczyć błąd, który generował.

Próba połączenia dała mi błąd Data source not found and no default driver specified . To dało mi wskazówkę, wskazując, że albo napisałem niepoprawny ciąg połączenia, albo że ciąg tekstowy został w jakiś sposób błędnie zinterpretowany lub zniekształcony.

Wykonywanie wyszukiwania w sieci dał mi wgląd, że ciąg został błędnie zinterpretowany, i aby to naprawić, musiałem uczynić go dosłownym ciągiem. Z pewnością postawienie litery L przed napisem rozwiązało ten problem!

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);

Jednocześnie nauczyłem się, jak pozbyć się monitu, co było dość łatwe do zrozumienia po naprawieniu początkowego problemu. Określ null dla uchwytu okna, ustaw uzupełnianie sterownika na SQL_DRIVER_COMPLETE i upewnij się, że dodałeś wszystkie potrzebne informacje w ciągu połączenia.

Więc kolejny problem, który miałem z zapytaniem z SQLExecDirect wyświetlał błąd mówiący Syntax error or access violation . Problem był oczywiście taki sam, jak w przypadku ciągu połączenia. Z pewnością

retcode = SQLExecDirect(hstmt, (SQLWCHAR*)L"SELECT TEST_STRING, TEST_INTEGER, TEST_FLOAT FROM dbo.testfire", SQL_NTS);

Działał jak urok.

Oto kod w całości, w pełni funkcjonalny:

#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;
}

Po prostu widać, że nawet najmniejsza rzecz może sprawić, że wszystko zawiedzie.

Dziękuję Mat za pomoc.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak działa funkcja OCTET_LENGTH() w MySQL

  2. Oczyszczanie zmiennych PHP, czy nadużywam ich?

  3. Grupuj MySQL według ostatniego wpisu

  4. Mysql CASE NIE ZNALEZIONO dla CASE STATEMENT w procedurze przechowywanej

  5. Określona kolumna nie jest wstawiana podczas zapisywania rekordu