C++中使用ODBC连接SQL Server数据库

整体总结

用odbc过时了,还是使用ado吧,易用,高效率,不用配置odbc数据源,易维护,实际项目已从odbc中改用了ado,请看我的这篇文章,有详细的封装实现:https://blog.csdn.net/lishenluo/article/details/108239084

坚持用odbc?那么继续这篇:

参考官网: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数据库那么方便(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数据源(地址,账号,密码等),这里就是通过这个数据源名称选择连接那个数据源。
.
在这里插入图片描述

在这里插入图片描述

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

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

#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);
}
  • 5
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在C语言使用ODBC连接SQL Server数据库,需要以下步骤: 1. 安装ODBC驱动程序:下载并安装Microsoft SQL Server ODBC驱动程序,使其能够被程序调用。 2. 初始化ODBC环境:使用SQLAllocHandle函数初始化ODBC环境,为后续的连接操作做准备。 3. 建立连接使用SQLConnect函数连接SQL Server数据库,需要提供数据库的名称、用户名和密码等信息。 4. 执行SQL语句:使用SQLExecDirect函数执行SQL语句,可以是查询语句或更新语句等。 5. 处理结果:使用SQLBindCol函数绑定查询结果的每一列,然后使用SQLFetch函数获取每一行的数据。 6. 释放资源:使用SQLFreeStmt和SQLDisconnect函数释放连接和环境资源。 以下是一个使用ODBC连接SQL Server数据库的示例: ``` #include <stdio.h> #include <sql.h> #include <sqlext.h> int main(void) { SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt; SQLRETURN retcode; SQLCHAR szDSN[] = "myDSN"; SQLCHAR szUID[] = "myUser"; SQLCHAR szPWD[] = "myPassword"; SQLCHAR szConnStr[1024]; SQLCHAR szSqlStmt[1024]; SQLCHAR szCol1[256]; SQLCHAR szCol2[256]; SQLINTEGER iCol1; SQLINTEGER iCol2; // 初始化ODBC环境 retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); // 建立连接 sprintf(szConnStr, "DSN=%s;UID=%s;PWD=%s", szDSN, szUID, szPWD); retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); retcode = SQLDriverConnect(hdbc, NULL, szConnStr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE); // 执行SQL语句 sprintf(szSqlStmt, "SELECT col1, col2 FROM myTable"); retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); retcode = SQLExecDirect(hstmt, szSqlStmt, SQL_NTS); // 处理结果 retcode = SQLBindCol(hstmt, 1, SQL_C_CHAR, szCol1, sizeof(szCol1), NULL); retcode = SQLBindCol(hstmt, 2, SQL_C_LONG, &iCol2, 0, NULL); while (SQLFetch(hstmt) == SQL_SUCCESS) { printf("%s, %d\n", szCol1, iCol2); } // 释放资源 retcode = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); retcode = SQLDisconnect(hdbc); retcode = SQLFreeHandle(SQL_HANDLE_DBC, hdbc); retcode = SQLFreeHandle(SQL_HANDLE_ENV, henv); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值