MariaDB + Visual Studio 2017 環境下的 ODBC 入門開發


參考:

Easysoft公司提供的ODBC教程

微軟提供的ODBC文檔

環境:

  • Windows 10 x64 1803
  • MariaDB TX 10.2.14 x64
  • MariaDB ODBC Connector 3.0.3 x64
  • Visual Studio 2017 Community 15.6.7

安裝ODBC驅動並配置數據源:

先安裝ODBC驅動。根據自身需求選擇32或64位版本。我選擇了64位版本。

打開ODBC數據源管理程序,點擊右側的“添加”按鈕,添加用戶DSN。如圖操作。

后面按照默認配置,點擊Next即可。

編寫ODBC程序:

1         引入頭文件:

#include <iostream>

#include <windows.h>

#include <sqlext.h>

2         定義一個檢查錯誤的宏:

#define ODBC_CHECK(x) \

{\

    if (!SQL_SUCCEEDED(x))\

    {\

        std::cout << "SQL error occurred at line " << __LINE__ << ".";\

        getchar();\

        exit(-1);\

    }\

}

3         ODBC初始化,為ODBC分配環境句柄

(分配環境句柄:注意,這里使用了新版的ODBC API SQLAllocHandle,而不是SQLAllocEnv

    // SQL Handle of ENVironment

    SQLHENV env;

    ODBC_CHECK(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env)); // SQLAllocEnv

  ODBC_CHECK(SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0));

4         建立應用程序與ODBC數據源的連接

(分配連接句柄:注意,這里使用了新版的ODBC API SQLAllocHandle,而不是SQLAllocConnect

    // SQL Handle of DB Connection

    SQLHDBC dbc;

    SQLCHAR dbcConfOut[256];

    ODBC_CHECK(SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc)); // SQLAllocConnect

    ODBC_CHECK(SQLSetConnectAttr(dbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0));

(連接數據源:可以使用SQLConnect,也可以使用SQLDriverConnect;可以手動指定DSN名字,也可以通過彈出窗口來指定)

    // specify manually

    ODBC_CHECK(SQLDriverConnect(dbc, NULL, (SQLCHAR *)"DSN=MariaDB;", SQL_NTS,

                                dbcConfOut, sizeof(dbcConfOut), NULL, SQL_DRIVER_COMPLETE)); // SQLConnect

    // specify by popup window

    //ODBC_CHECK(SQLDriverConnect(dbc, GetDesktopWindow(), NULL, SQL_NTS,

    //                            dbcConfOut, sizeof(dbcConfOut), NULL, SQL_DRIVER_COMPLETE)); // SQLConnect

(顯示連接成功的信息)

    std::cout << "Connected!" << std::endl

        << "ConnStrIn = " << dbcConfOut << std::endl;

 

    SQLCHAR dbmsName[256];

    ODBC_CHECK(SQLGetInfo(dbc, SQL_DBMS_NAME, (SQLPOINTER)dbmsName, sizeof(dbmsName), NULL));

    SQLCHAR dbmsVer[256];

    ODBC_CHECK(SQLGetInfo(dbc, SQL_DBMS_VER, (SQLPOINTER)dbmsVer, sizeof(dbmsVer), NULL));

    std::cout << "DBMS Name = " << dbmsName << std::endl

        << "DBMS Version = " << dbmsVer << std::endl;

(分配語句句柄:注意,這里使用了新版的ODBC API SQLAllocHandle,而不是SQLAllocStmt

    // SQL Handle of STateMenT

    SQLHSTMT stmt;

    ODBC_CHECK(SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt)); // SQLAllocStmt

5         利用SQLExecDirect語句,實現數據庫應用程序對數據庫的建立、查詢、修改、刪除等 

(建立一個循環,一直接收並執行用戶的SQL的語句,直到用戶退出)

    const int queryLen = 1024;

    SQLCHAR query[queryLen];

    std::cout << "Please input your SQL query. Type CTRL+Z to quit." << std::endl

        << dbmsName << " >";

    while (fgets((char*)query, queryLen - 1, stdin))

    {

        if (query[0] == '\n')

        {

            std::cout << dbmsName << " >";

            continue;

        }

 

        switch (SQLExecDirect(stmt, query, SQL_NTS))

        {

            case SQL_SUCCESS_WITH_INFO:

            case SQL_SUCCESS:

            {

                SQLSMALLINT col;

                SQLNumResultCols(stmt, &col);

                // SELECT

                if (col > 0)

                {   // 2 methods: SQLGetData() and SQLBindCol()

                    // SQLGetData() is adopted here

 

                    char buf[512];

                    SQLUSMALLINT colidx;

                    // print column names

                    for (colidx = 1; colidx <= col; ++colidx)

                    {

                        SQLColAttribute(stmt, colidx, SQL_DESC_NAME,

                                        buf, sizeof(buf), NULL, NULL);

                        std::cout << buf << " ";

                    }

                    std::cout << std::endl;

 

                    // iterate each row

                    unsigned row = 0; // row counter

                    while (SQL_SUCCEEDED(SQLFetch(stmt)))

                    {

                        ++row;

                        // iterate each column

                        for (colidx = 1; colidx <= col; ++colidx)

                        {

                            SQLLEN indicator;

                            if (SQL_SUCCEEDED(SQLGetData(stmt, colidx, SQL_C_CHAR,

                                                         buf, sizeof(buf), &indicator)))

                            {

                                if (indicator == SQL_NULL_DATA) strcpy(buf, "NULL");

                                std::cout << buf << " ";

                            }

                        }

                        std::cout << std::endl;

                    }

                    if (row == 1) { std::cout << "1 row in set." << std::endl; }

                    else { std::cout << row << " rows in set." << std::endl; }

                }

                // CREATE, UPDATE, DELETE, etc.

                else

                {

                    SQLLEN row;

                    ODBC_CHECK(SQLRowCount(stmt, &row));

                    if (row == 1) { std::cout << "1 row affected." << std::endl; }

                    else { std::cout << row << " rows affected." << std::endl; }

                }

                break;

            }

            case SQL_ERROR:

            {

                std::cout << "Returned SQL_ERROR." << std::endl;

                break;

            }

            default:

            {

                std::cout << "Unknown SQLRETURN." << std::endl;

            }

        }

 

        ODBC_CHECK(SQLFreeStmt(stmt, SQL_CLOSE));

        std::cout << dbmsName << " >";

    }

6         檢索查詢結果集 

7         結束數據庫應用程序

    // release resources

    ODBC_CHECK(SQLFreeHandle(SQL_HANDLE_STMT, stmt));

    ODBC_CHECK(SQLDisconnect(dbc));

    ODBC_CHECK(SQLFreeHandle(SQL_HANDLE_DBC, dbc));

    ODBC_CHECK(SQLFreeHandle(SQL_HANDLE_ENV, env));

    return 0;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM