Подключение к базе данных на C++

107
18 марта 2021, 22:50

Пытаюсь подключиться к базе данных SQL через плюсы.

База в файле, сервер - локальный.

Если отправить запрос на считывание из базы: SELECT * FROM Vertex, то выскакивает ошибка, что недопустимое имя "Vertex".

Может быть кто-то знает, что не так происходит?

Answer 1

По приведенным данным трудно понять, в чем ошибка. Я рекомендую вместо MFC использовать классический C API ODBC, который дает чуть больше контроля над происходящим.

Вот рабочий пример подключения к SQL Server с помощью ODBC:

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <sqlext.h>
#include <locale.h>
WCHAR szDSN[] = L"Driver={SQL Server};DSN='';SERVER=.\\sqlexpress;DATABASE=mydatabase;";
WCHAR query[] = L"SELECT * FROM Table";
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++;
    }
}
int _tmain(int argc, _TCHAR* argv[])
{   
    HENV    hEnv = NULL;
    HDBC    hDbc = NULL;
    HSTMT hStmt = NULL;
    int iConnStrLength2Ptr;
    WCHAR szConnStrOut[256];
    SQLINTEGER rowCount = 0;
    SQLSMALLINT fieldCount = 0, currentField = 0;
    SQLWCHAR buf[128],colName[128]; 
    SQLINTEGER ret;
    /* ODBC API return status */
    RETCODE rc;
    setlocale(LC_ALL, "Russian");
    /* 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"\n- Columns -\n");
            SQLNumResultCols(hStmt, &fieldCount);
            if (fieldCount > 0)
            {   
                for (currentField = 1; currentField <= fieldCount; currentField++)
                {
                    SQLDescribeCol(hStmt, currentField,
                        colName, sizeof(colName), 0, 0, 0, 0, 0);
                    wprintf(L"%d: %s\n", (int)currentField, colName);
                }
                wprintf(L"\n");
                /* Loop through the rows in the result set */                               
                rc = SQLFetch(hStmt);
                while (SQL_SUCCEEDED(rc))
                {
                    wprintf(L"- Record #%d -\n", (int)rowCount);
                    for (currentField = 1; currentField <= fieldCount; currentField++)
                    {
                        rc = SQLGetData(hStmt, currentField, SQL_C_WCHAR, buf, sizeof(buf), &ret);
                        if (SQL_SUCCEEDED(rc) == FALSE) {
                            wprintf(L"%d: SQLGetData failed\n", (int)currentField);
                            continue;
                        }
                        if (ret <= 0) {
                            wprintf(L"%d: (no data)\n", (int)currentField);
                            continue;
                        }
                        wprintf(L"%d: %s\n", (int)currentField, buf);
                    }                   
                    wprintf(L"\n");
                    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);
    getchar();
    return 0;
}

Если нужно подключиться к mdf-файлу, строка подключения szDSN будет иметь вид:

Driver={SQL Server};DSN='';SERVER=.\\SQLEXPRESS;AttachDBFileName=C:\\base\\db.mdf;

Параметры строки подключения:

  • Driver: по ситуации (в зависимости от того, к какой версии SQL Server на какой ОС и как именно подключаетесь и что пытаетесь делать) возможно понадобится поменять на SQL Server Native Client XX.0, где ХХ - используемая версия. Например SQL Server Native Client 11.0 для SQL 2012.

  • Server: путь к экземпляру вида (IP или имя сервера)\(имя экземпляра). Точка означает localhost. Если используется экземпляр по умолчанию, имя экземпляра и косую черту нужно опустить

  • DataBase: имя БД, уже присоединенной к серверу.

  • AttachDBFileName: путь к файлу БД для подключения (Внимание - при таком сценарии он будет открыт монопольно, пока вы работаете с соединением!).

Для аутентификации по логину и паролю необходимо добавить UID=login;PWD=password (по умолчанию используется Windows-аутентификация от имени текущего пользователя).

Если не уверены в параметрах соединения, можно поэкспериментировать через Панель управления - Администрирование - Источники данных ODBC. Создаете файловый DSN с нужными параметрами, тестируете его, а затем открываете в блокноте и копируете параметры.

READ ALSO
Алгоритм детектора прямых линий

Алгоритм детектора прямых линий

Есть задача - написать алгоритм детектора, который ищет прямые линии на изображении, и записывает эти линии в простом виде с параметрами,...

87
Не могу создать цикл для операции xor

Не могу создать цикл для операции xor

Наткнулся на задание с шифрованием через XORВ нем было сказано, что нужно вводить ключ в программу 3-мя способами

112
Можно ли вызывать std::move несколько раз?

Можно ли вызывать std::move несколько раз?

Корректен ли подобный код?

91
Недопустимое имя столбца в запросе

Недопустимое имя столбца в запросе

Есть запрос, который содержит кириллические символы(думаю вся проблема в них)

76