文章目录

  • 整体总结
  • ODBC连接
  • 一个修改别人的整体的例子


整体总结

用odbc过时了,还是使用ado吧,易用,高效率,不用配置odbc数据源,易维护,实际项目已从odbc中改用了ado,


参考官网:https://docs.microsoft.com/zh-cn/sql/odbc/reference/syntax/sqlallochandle-function?view=sql-server-ver15

ODBC访问sql server数据库,比较麻烦。没有像使用occi那样访问oracle数据库那么方便(lsl20200817修正:occi访问oracle获取股票列表并不见得有多快,目前只是觉得能用就不改进了)。 批量操作并不好。如获取数据,执行sql后,还需要循环一个个取数据,很是麻烦,需要输入要获取的数据的类型。

可以所有列都是按SQL_C_CHAR字符类型来获取,后续使用数据的时候再转类型。代码如下:

int selectData(const string& sql,vector<string>& results)
{
    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)
        {
            midData[0] =  0 ; //注意这里:重新赋空
            ret = SQLGetData(hstmt1, col, SQL_C_CHAR, midData, MAXCHAR, &midDataLength);
            if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
            {
                ss << "," << midData;
            }
        }
        results.emplace_back(ss.str());//一个string就是表格的一行,用逗号分隔
    }
	SQLCancel(hstmt1); //注意,回到前一个状态,否则下次查询查不到哦
}

ODBC连接

SQLConnect的时候,使用的是odbc数据库源名称,在odbc数据源中设置。windows中安装了sql server manager后,相应的odbc应该也安装了,没有安装的话安装一个。然后配置一个odbc数据源(地址,账号,密码等),这里就是通过这个数据源名称选择连接那个数据源。

.

C语言使用oDBC连接Mysql数据库 使用odbc连接sqlserver_ODBC



C语言使用oDBC连接Mysql数据库 使用odbc连接sqlserver_C语言使用oDBC连接Mysql数据库_02

一个修改别人的整体的例子

这里只是测试验证,实际中我是封装了类的。否则就太乱了。

#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() {
    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);
}