vlambda博客
学习文章列表

C++控制台程序使用ODBC连接SQLServer

连接:

一、设置ODBC 的数据源

二、进行代码连接

 

总流程:

1、申请环境句柄

2、配置环境句柄

3、申请连接句柄

4、定义数据库名、用户名、用户密码

5、连接数据库,并验证是否连接成功

6、申请语句句柄

7、定义要执行的语句

8、执行语句

9、释放申请的句柄

 

1、申请环境句柄:

函数讲解:

SQLRETURN SQLAllocHandle(

     SQLSMALLINT     HandleType,    // 输入变量类型

     SQLHANDLE     InputHandle,     // 输入变量

     SQLHANDLE *     OutputHandlePtr);    // 输出变量

 

HandleType:

 

SQL_HANDLE_ENV:用于申请环境句柄     SQLHENV

SQL_HANDLE_DBC :用于申请连接句柄     SQLHDBC

 

SQL_HANDLE_DESC:用于申请描述符句柄      SQLHDESC

SQL_HANDLE_STMT:用于申请语句句柄       SQLHSTMT

InputHandle:

该变量放入已经被分配好的前提句柄,如果第一个变量为环境句柄,则放入SQL_NULL_HANDLE即可,若果第一个变量为SQL_HANDLE_DBC,则第二个变量必须为已分配的环境句柄,如第一个变量为SQL_HANDLE_DESC,SQL_HANDLE_STMT则,第二个变量必须为已分配好的连接句柄。

OutputHandlePtr :

该变量为一个指针变量,用于保存申请来的句柄,申请句柄类型为第一个变量,在定义该指针的时候需注意类型一致。

返回值:

返回值有四种:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_INVALID_HANDLE, or SQL_ERROR.


2、设置控制环境各个方面的特性。

SQLRETURN SQLSetEnvAttr(

     SQLHENV     EnvironmentHandle,     // 环境句柄

     SQLINTEGER     Attribute,                  // 数据库连接池的属性

     SQLPOINTER     ValuePtr,                  // 和参数二对应的属性

     SQLINTEGER     StringLength);          // 一个参数的长度

EnvironmentHandle:要进行配置的环境的句柄

Attribute:要进行配置的属性

ValuePtr:要与 属性 关联的值的指针。根据 属性 的值, 将 valueptr 将为32位整数值,或指向以 null 值结束的字符串。

图片来自(  https://www.cnblogs.com/jadeshu/p/10663678.html)

二者更详细关系说明参考: https://docs.microsoft.com/zh-cn/sql/odbc/reference/syntax/sqlsetenvattr-function?view=sql-server-ver15

StringLength:将 valueptr 指向某个字符串或二进制缓冲区,则此参数应为 *将 valueptr 的长度。对于字符串数据,此参数应包含字符串中的字节数。

如果 将 valueptr 是一个整数,则将忽略 StringLength 。

返回值:

返回值有四种:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_INVALID_HANDLE, or SQL_ERROR.

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

连接数据库:

SQLRETURN SQLConnect(

     SQLHDBC     ConnectionHandle,     // 连接句柄      

     SQLCHAR *     ServerName,             //  数据库名

     SQLSMALLINT     NameLength1,     //  数据库名长度

     SQLCHAR *     UserName,               //  用户名

     SQLSMALLINT     NameLength2,     //  用户名长度

     SQLCHAR *     Authentication,         //  密码

     SQLSMALLINT     NameLength3);    //  密码长度

返回值:

返回值有四种:SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_INVALID_HANDLE, or SQL_ERROR.

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

执行 sql 语句:

SQLRETURN SQLExecDirect(

                         SQLHSTMT StatementHandle, // 语句句柄

                         SQLCHAR * StatementText, // 要执行的语句

                         SQLINTEGER TextLength); // 语句长度

 

--------------------------------------------------------------------------------------------------------------------------------------------------

从结果集中提取下一个数据行集,并返回所有绑定列的数据。

SQLRETURN SQLFetch(

                    SQLHSTMT StatementHandle // 语句句柄

    );

 

返回值:

SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_NO_DATA、SQL_STILL_EXECUTING、SQL_ERROR 或 SQL_INVALID_HANDLE。

---------------------------------------------------------------------------------------------------------------------------------------------

检索结果集中单个列的数据,或在 SQLParamData 返回 SQL_PARAM_DATA_AVAILABLE 之后为单个参数检索数据。 可以多次调用此方法,以便在部分中检索可变长度数据。

SQLRETURN SQLGetData(

                        SQLHSTMT StatementHandle, // 语句句柄

                        SQLUSMALLINT Col_or_Param_Num, // 要检索列数据,它是要为其返回数据的列的编号。 结果集列按递增的列顺序编号,从1开始。

                        SQLSMALLINT TargetType, // 该列的数据类型

                        SQLPOINTER TargetValuePtr, // 指向要返回数据的缓冲区的指针。不能为 NULL

                        SQLLEN BufferLength, // 缓冲区的长度

                        SQLLEN * StrLen_or_IndPtr // 一个指针,指向要返回其长度或指示器值的缓冲区。 如果这是 null 指针,则不返回长度或指示器值。 当提取的数据为空时,这将返回错误。

);

返回值:

SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_NO_DATA、SQL_STILL_EXECUTING、SQL_ERROR 或 SQL_INVALID_HANDLE。

---------------------------------------------------------------------------------------------------------------------------------------------

 

 

 


 

 

 

 

 

函数使用:

SQLHENV renv;  

SQLHDBC rdbc;

SQLRETURN res;

res = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&renv) ;   // 创建申请环境句柄

res = SQLSetEnvAttr(renv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);           //设置控制环境的各个属性

res = SQLAllocHandle(SQL_HANDLE_DBC,renv,&rdbc)    // 创建申请连接句柄

//定义变量,存放数据库名,用户名和密码

SQLWCHAR db[] = '数据库名';

SQLWCHAR  user[] = "用户名";

SQLWCHAR pwd[] = "密码";

// 进行数据库连接

res = SQLConnect(rdbc,db,SQL_NTS,user,SQL_NTS,pwd,SQL_NTS);

//  验证数据库是否连接成功

if(!(res == SQL_SUCCESS) || res == SQL_SUCCESS_WITH_INFO)

{

       cout<<"数据库连接失败";

       rerturn -1;

}

//  因为要进行数据可操作,使用数据库语句,申请语句句柄

SQLHSTMT rstmt;

res = SQLAllocHandle( SQL_HANDLE_STMT,rdbc,&rstmt) ;   // 创建申请环境句柄

 

// 插入数据

SQLWCHAR sql1[] = L"insert into first.dbo.v1 (a,b,c,d,h,m) values  ('a5','b5',28,25,24,'s')";

       ret = SQLExecDirect(hstmt, sql1, SQL_NTS);

       if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)

       {

              std::cout << "插入成功!";

       }

       else

       {

              std::cout << ret << "\n";

              std::cout << "插入失败!";

       }

// 修改数据

SQLWCHAR sql3[] = L"update first.dbo.v1 set a='ak',b='bk',c=19,d=18 where a='aa'";

       ret = SQLExecDirect(hstmt, sql3, SQL_NTS);

       if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)

       {

              std::cout << "修改成功!";

       }

       else

       {

              std::cout << ret << "\n";

              std::cout << "修改失败!";

       }

// 查询数据库表语句

SQLWCHAR sqlsel[] = "select * from first.dbo.v1";

//  执行语句

res = SQLExecDirect(rstmt,sqlsel,SQL_NTS);

//  遍历查到的数据库结果

if(res == SQL_SUCCESS  || res == SQL_SUCCESS_WITH_INFO)

{

     // 遍历

    while(SQLFetch(rstmt) != SQL_NO_DATA)

    {

        // 获取每列中的数据

        SQLCHAR str1[20],str2[20],str3[20],str4[20];

        SQLINTEGER len_str1,len_str2,len_str3,len_str4;

        SQLGetData(rstmt,1,SQL_C_CHAR,str1,40,&len_str1);

        SQLGetData(rstmt,2,SQL_C_CHAR,str2,40,&len_str2);

        SQLGetData(rstmt,3,SQL_C_CHAR,str3,40,&len_str3);

        SQLGetData(rstmt,4,SQL_C_CHAR,str4,40,&len_str4);

    }

}

//  注:如果在查询表数据之后执行插入或者删除操作(使用同一个句柄 rstmts),会导致失败。目前还未想通原因,有没有大佬知道,请指教!万分感谢!

//  释放连接的句柄

SQLFreeHandle(SQL_HANDLE_DBC,rdbc);

SQLFreeHandle(SQL_HANDLE_ENV,renv);

SQLFreeHandle(SQL_HANDLE_STMT, hstmt);//释放环境句柄

 

整体代码