總結下
參考官網: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);
}