【问题标题】:C++ Database get array of rows from a table using SQL ODBCC++ 数据库使用 SQL ODBC 从表中获取行数组
【发布时间】:2021-06-09 22:28:22
【问题描述】:

参考此链接C++\SQL ODBC: Get row from table 我不理解这些文档,并尝试了许多变体来使某些东西起作用,但它只会输出完整的胡言乱语。基本上,我怎样才能从我的 Microsoft Access 数据库中获取数据到我的 C++ 程序中。我最终希望将整个表存储为数组或向量,也就是说,假设我的表中有 5 个字段,我想将所有内容存储(在 5 个不同的数组或向量中)到相应的字段。但是现在,我怎么能只拥有一个名为“示例表”的表,其中有一个名为“名称”的字段,并且类型是 Access 所称的字符串或“短文本”。然后如何将其加载到字符串数组或 char* 中以用于我的 GUI 或程序的其他部分?这是我当前的代码:

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <sqlext.h>
#include <iostream>

WCHAR szDSN[] = L"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=C:\\Users\\Name\\Desktop\\databaseExample\\databaseExample\\Data.accdb";

int _tmain(int argc, _TCHAR* argv[])
{

    HENV    hEnv;
    HDBC    hDbc;

    /* ODBC API return status */
    RETCODE rc;

    int     iConnStrLength2Ptr;
    WCHAR    szConnStrOut[256];

    const WCHAR* query = L"select Names from Example_Table";

    HSTMT           hStmt;

    /* Allocate an environment handle */
    rc = SQLAllocEnv(&hEnv);
    /* Allocate a connection handle */
    rc = SQLAllocConnect(hEnv, &hDbc);

    /* Connect to the database */
    rc = SQLDriverConnect(hDbc, NULL, (WCHAR*)szDSN,
        SQL_NTS, (WCHAR*)szConnStrOut,
        255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
    if (SQL_SUCCEEDED(rc))
    {

        wprintf(L"Successfully connected to database. Data source name: \n  %s\n",
            szConnStrOut);

        /* Prepare SQL query */
        wprintf(L"SQL query:\n  %s\n", query);

        rc = SQLAllocStmt(hDbc, &hStmt);
        rc = SQLPrepare(hStmt, (SQLWCHAR*)query, SQL_NTS);

        /* Excecute the query */
        rc = SQLExecute(hStmt);
        if (SQL_SUCCEEDED(rc))
        {
            wprintf(L"SQL Success\n");
        }
        else {
            wprintf(L"SQL Failed\n");
        }
        
    }
    else
    {
        wprintf(L"Couldn't connect to %s.\n", szDSN);
    }

    /* Disconnect and free up allocated handles */
    SQLDisconnect(hDbc);
    SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);

    getchar();
    printf("hi\n");
    return 0;
}

【问题讨论】:

    标签: c++ sql database ms-access odbc


    【解决方案1】:

    您需要使用SQLGetData,传递SQL_C_WCHAR 类型,例如,如果您的列是文本。下面是如何获取单个文本列的值并将它们放入向量的示例:

    #include <iostream>
    #include <string>
    #include <vector>
    #include <Windows.h>
    #include <sqlext.h>
    
    WCHAR szDSN[] = L"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=C:\\Test\\users.accdb";
    
    void DisplayError(SQLSMALLINT t, SQLHSTMT h) {
        SQLWCHAR       SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
        SQLINTEGER    NativeError;
        SQLSMALLINT   i, MsgLen;
        SQLRETURN     rc;
    
        SQLLEN numRecs = 0;
        SQLGetDiagField(t, h, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
    
        // Get the status records.
        i = 1;
        while (i <= numRecs && (rc = SQLGetDiagRec(t, h, i, SqlState, &NativeError,
            Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) {
            wprintf(L"Error %d: %s\n", NativeError, Msg);
            i++;
        }
    
    }
    
    std::vector<std::wstring> ExecuteSql(const WCHAR* sql) {
    
        std::vector<std::wstring> results = {};
        HENV    hEnv = NULL;
        HDBC    hDbc = NULL;
        HSTMT hStmt = NULL;
        int iConnStrLength2Ptr;
        WCHAR szConnStrOut[256];
        SQLINTEGER rowCount = 0;
        SQLSMALLINT fieldCount = 0;
        SQLWCHAR buf[128];
        SQLINTEGER ret;
    
        /* ODBC API return status */
        RETCODE rc;
    
        /* Allocate an environment handle */
        rc = SQLAllocEnv(&hEnv);
        /* Allocate a connection handle */
        rc = SQLAllocConnect(hEnv, &hDbc);
    
        /* Connect to the database */
        rc = SQLDriverConnect(hDbc, NULL, (WCHAR*)szDSN,
            SQL_NTS, (WCHAR*)szConnStrOut,
            255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
    
        if (SQL_SUCCEEDED(rc))
        {
            /* Prepare SQL query */
            rc = SQLAllocStmt(hDbc, &hStmt);
            rc = SQLPrepare(hStmt, (SQLWCHAR*)sql, SQL_NTS);
    
            /* Excecute the query */
            rc = SQLExecute(hStmt);
            if (SQL_SUCCEEDED(rc))
            {
                SQLNumResultCols(hStmt, &fieldCount);
    
                if (fieldCount > 0)
                {
                    /* Loop through the rows in the result set */
    
                    rc = SQLFetch(hStmt);
    
                    while (SQL_SUCCEEDED(rc))
                    {                   
                        //get data
                        rc = SQLGetData(hStmt, 1, SQL_C_WCHAR, buf, sizeof(buf), &ret);
                        
                        if (SQL_SUCCEEDED(rc) == FALSE) {
                            wprintf(L"SQLGetData failed\n");
                            continue;
                        }
    
                        //convert data to string
                        std::wstring str;
                        if (ret <= 0) {
                            str = std::wstring(L"(null");
                        }
                        else {
                            str = std::wstring(buf);
                        }
                        
                        results.push_back(str);
                        rc = SQLFetch(hStmt);
                        rowCount++;
                    };
    
                    rc = SQLFreeStmt(hStmt, SQL_DROP);
    
                }
                else
                {
                    wprintf(L"Error: Number of fields in the result set is 0.\n");
                }
    
            }
            else {
                wprintf(L"SQL Failed\n");
                DisplayError(SQL_HANDLE_STMT, hStmt);
            }
        }
        else
        {
            wprintf(L"Couldn't connect to %s\n", szDSN);
            DisplayError(SQL_HANDLE_DBC, hDbc);
        }
    
        /* Disconnect and free up allocated handles */
        SQLDisconnect(hDbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return results;
    }
    
    int main()
    {
        auto results = ExecuteSql(L"SELECT name FROM Users");
    
        for (auto x : results) {
            std::wcout << x << std::endl;
        }
    
        getchar();
        return 0;
    }
    

    【讨论】:

    • 哇,我什至不能感谢你!这为我节省了大量时间,我深入使用 C++/CLI 作为解决方案,但它一直限制我使用本地 C++ 中不可用的特定包含,非常感谢!!
    猜你喜欢
    • 1970-01-01
    • 2011-04-02
    • 2013-05-24
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    相关资源
    最近更新 更多