C++中使用ODBC連接SQL Server數據庫

總結下

參考官網:https://docs.microsoft.com/zh-cn/sql/odbc/reference/syntax/sqlallochandle-function?view=sql-server-ver15
有用的博客1:https://blog.csdn.net/serg_/article/details/1618317
有用的博客2:https://www.cnblogs.com/MakeView660/p/9578236.html

ODBC訪問sql server數據庫,比較麻煩。沒有像使用occi那樣訪問oracle數據庫那麼方便。 批量操作並不好。如獲取數據,執行sql後,還需要循環一個個取數據,很是麻煩,需要輸入要獲取的數據的類型。
後來直接全部用字符數組類型獲取。如下:

int selectData(const string& sql)
{
    CHAR csql[SQL_MAX_OPTION_STRING_LENGTH] = { 0 };
    strcpy_s(csql, sql.c_str());
    RETCODE ret = SQLExecDirect(hstmt1, (SQLCHAR*)csql, strlen(csql));
    if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO)
    {
        LLogError("select data error,error code:"<<ret);
        return ret;
    }
    SQLCHAR midData[MAXCHAR] = { 0 };
    SQLLEN midDataLength = 0;
    SQLSMALLINT columnCount = 0;
    SQLNumResultCols(hstmt1,&columnCount);
    int line = 0;
    while (SQLFetch(hstmt1) != SQL_NO_DATA_FOUND)
    {
        // 參數1爲執行語句的句柄,
        // 參數2爲所要得到的數據位於的列數(SQL語句中),
        // 參數3爲數據類型,這個比較多,需要看一下MSDN
        // 參數4爲保存的位置(地址),
        // 參數5爲參數4可用的位置,既然參數3已設定爲長整型,所以這裏可使用0
        // 參數6爲實際返回的長度
        stringstream ss;
        ++line;
        ss << line;
        for (int col = 1; col <= columnCount; ++col)
        {
            ret = SQLGetData(hstmt1, col, SQL_C_CHAR, midData, MAXCHAR, &midDataLength);
            if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
            {
                ss << "," << midData;
            }
        }
        //LLogInfo(ss.str());
    }

}

一個修改別人的例子

這裏只是測試驗證,實際中我是封裝了類的。否則就太亂了。

#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <odbcss.h>
SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc1 = SQL_NULL_HDBC;
SQLHSTMT hstmt1 = SQL_NULL_HSTMT;

/*
    cpp文件功能說明:
    1.數據庫操作中的添加,修改,刪除,主要體現在SQL語句上
    2.採用直接執行方式和參數預編譯執行方式兩種
*/
int main() {
    return 0;
    RETCODE retcode;
    UCHAR   szDSN[SQL_MAX_DSN_LENGTH + 1] = "dataservice", //odbc數據庫源名稱,在odbc數據源中設置。windows中安裝了sql server manager後,相應的odbc應該也安裝了吧,沒有安裝的話安裝一個。然後配置一個odbc數據源(地址,賬號,密碼等),這裏就是通過這個數據源名稱選擇連接那個數據源。
        szUID[MAXNAME] = "sa",
        szAuthStr[MAXNAME] = "11";
    //SQL語句  
        //直接SQL語句  
    UCHAR   sql[74] = "SELECT * FROM[DataService].[dbo].[DailyFacts] where stockId = '600036.sh'";// "insert into test values('aaa','100')";
    //預編譯SQL語句  
    UCHAR   pre_sql[29] = "insert into test values(?,?)";
    //1.連接數據源  
        //1.環境句柄  
    retcode = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);
    retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
        (SQLPOINTER)SQL_OV_ODBC3,
        SQL_IS_INTEGER);
    //2.連接句柄    
    retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);
    retcode = SQLConnect(hdbc1, szDSN, 12, szUID, 2, szAuthStr, 2);
    UCHAR   conInfo[125] = "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Password=sa;Initial Catalog=DataService;Data Source=10.101.223.13";
    SQLCHAR* pwszConnStr=NULL;
    //retcode = SQLDriverConnect(hdbc1,
    //    GetDesktopWindow(),
    //    pwszConnStr,
    //    SQL_NTS,
    //    NULL,
    //    0,
    //    NULL,
    //    SQL_DRIVER_COMPLETE);


    //判斷連接是否成功  
    if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) {
        printf("連接失敗!\n");
    }
    else {
        //2.創建並執行一條或多條SQL語句  
        /*
        1.分配一個語句句柄(statement handle)
        2.創建SQL語句
        3.執行語句
        4.銷燬語句
        */
        retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);
        //第一種方式  
        //直接執行  
        //添加操作  
        retcode=SQLExecDirect (hstmt1,sql,74);
        if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
        {
            return 0;
        }
        SQLCHAR sqlnID[MAXCHAR] = {0};
        SQLLEN sqlnIDLength = 0;
        SQLCHAR columnName[MAXCHAR] = { 0 };
        SQLSMALLINT DataType= 0;
        SQLSMALLINT NameLength = 0;
        SQLULEN columnsize = 0;
        SQLSMALLINT dd = 0;
        SQLSMALLINT na = 0;
        SQLSMALLINT ddd = 0;
        ///* SQL data type codes */
        //#define SQL_UNKNOWN_TYPE    0
        //#define SQL_CHAR            1
        //#define SQL_NUMERIC         2
        //#define SQL_DECIMAL         3
        //#define SQL_INTEGER         4
        //#define SQL_SMALLINT        5
        //#define SQL_FLOAT           6
        //#define SQL_REAL            7
        //#define SQL_DOUBLE          8
        //#if (ODBCVER >= 0x0300)
        //#define SQL_DATETIME        9
        //#endif
        //#define SQL_VARCHAR         12
        //#if (ODBCVER >= 0x0300)
        //#define SQL_TYPE_DATE       91
        //#define SQL_TYPE_TIME       92
        //#define SQL_TYPE_TIMESTAMP  93
        //#endif
        TIMESTAMP_STRUCT datetime;
        while (SQLFetch(hstmt1) != SQL_NO_DATA_FOUND)
        {
            /* 獲得數據 */
            SQLGetData(hstmt1, 1, SQL_C_CHAR, sqlnID, MAXCHAR, &sqlnIDLength);
            SQLDescribeCol(hstmt1, 3, columnName, 128, &NameLength, &DataType, &columnsize, &dd, &na);
            SQLGetData(hstmt1, 5, SQL_C_SHORT, &ddd, sizeof(ddd), &sqlnIDLength);
            SQLGetData(hstmt1, 3, SQL_C_TIMESTAMP, &datetime, sizeof(datetime), &sqlnIDLength);
            // 參數1爲執行語句的句柄,
            // 參數2爲所要得到的數據位於的列數(SQL語句中),
            // 參數3爲數據類型,這個比較多,需要看一下MSDN
            // 參數4爲保存的位置(地址),
            // 參數5爲參數4可用的位置,既然參數3已設定爲長整型,所以這裏可使用0
            // 參數6爲實際返回的長度
        }

        //第二種方式  
        //綁定參數方式  
        char a[200] = "bbb";
        char b[200] = "200";
        INT64   p = SQL_NTS;
        //1預編譯  
        //SQLPrepare(hstmt1, pre_sql, 29); //第三個參數與數組大小相同,而不是數據庫列相同  
        ////2綁定參數值  
        //SQLBindParameter(hstmt1, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 200, 0, &a, 0, &p);
        //SQLBindParameter(hstmt1, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 200, 0, &b, 0, &p);
        ////3 執行  
        //SQLExecute(hstmt1);

        printf("操作成功!");
        //釋放語句句柄  
        SQLCloseCursor(hstmt1);
        SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);

    }
    //3.斷開數據源  
    /*
     1.斷開與數據源的連接.
     2.釋放連接句柄.
     3.釋放環境句柄 (如果不再需要在這個環境中作更多連接)
    */
    SQLDisconnect(hdbc1);
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
    return(0);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章