OCI连接Oracle调用OCISessionBegin失败:ORA-24314: 未初始化服务句柄

OCI连接Oracle数据库的时候,建立会话连接OCISessionBegin就失败:Error code为:ORA-24314: 未初始化服务句柄。
而使用PL/SQL Developer连接Oracle就可以,进去PL/SQL Developer里面也可以执行SQL语句。

小弟是小白,刚看C++如何操作Oracle,看网博上有那么一段代码就整下来试试,没什么经验,严重被打击中。。。代码如下:

::OCIEnv *envhpp = NULL; //初始化OCI环境句柄指针
::OCIServer *servhpp = NULL; //初始化服务器句柄
::OCIError *errhpp = NULL; //用于捕获OCI错误信息
::OCISession *usrhpp = NULL; //初始化会话句柄
::OCISvcCtx *svchpp = NULL; //初始化服务上下文句柄
::OCIStmt *stmthpp = NULL; //初始化表达式句柄

string  server = "DB_TEST";

// 创建 OCI 环境 , 并设置环境句柄
sword swResult = ::OCIEnvCreate( &envhpp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);
if (swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
{
    cout << "Oracle environment initialization error!" << endl;
    exit(1);
}

cout << "Oracle environment initialization success!" << endl;

// 创建错误句柄
 ::OCIHandleAlloc( (dvoid *)envhpp, (dvoid **)&errhpp, OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0 );

// 创建服务句柄
 ::OCIHandleAlloc( (dvoid *)envhpp, (dvoid **)&servhpp, OCI_HTYPE_SERVER, (size_t)0, (dvoid **)0 );

// 连接服务器,如果失败则获取错误码
if ( OCIServerAttach( servhpp, errhpp, (text *)server.c_str(), strlen(server.c_str()), OCI_DEFAULT ) != OCI_SUCCESS )
{
    int errcno;
    char errbuf[512] = {0};
    sb4 errcode;

    // 获取错误指针和 OCI错误码
    ::OCIErrorGet( (dvoid *)errhpp, (ub4)1, (text *)NULL, &errcode, (ub1 *)errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
    errcno = errcode;

    cout << "Oracle server attach error:" << errbuf << endl;
    ::OCIHandleFree( (dvoid *)errhpp, OCI_HTYPE_ERROR);
    ::OCIHandleFree( (dvoid *)servhpp, OCI_HTYPE_SERVER);
    ::OCIHandleFree( (dvoid *)envhpp, OCI_HTYPE_ENV);
    exit(1);
}

// 连接数据库
string user = "xiaobai";
string pas = "xiaobai";
errhpp = NULL;

// 创建错误句柄
::OCIHandleAlloc( (dvoid *)envhpp, (dvoid **)&errhpp, OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0 );

// 创建服务上下文句柄
::OCIHandleAlloc( (dvoid *)envhpp, (dvoid **)&svchpp, OCI_HTYPE_SVCCTX, (size_t)0, (dvoid **)0 );

// 设置属性
::OCIAttrSet( (dvoid *)svchpp, (ub4)OCI_HTYPE_SVCCTX, (dvoid *)servhpp, (ub4)0, (ub4)OCI_HTYPE_SERVER, (OCIError *)errhpp);


// 创建用户连接句柄
::OCIHandleAlloc( (dvoid *)envhpp, (dvoid **)&usrhpp, (ub4)OCI_HTYPE_SESSION, (size_t)0, (dvoid **)0);

// 设置用户名、密码
 ::OCIAttrSet( (dvoid *)usrhpp, (ub4)OCI_HTYPE_SESSION, (dvoid *)user.c_str(), (ub4)strlen(user.c_str()), (ub4)OCI_ATTR_USERNAME, errhpp);

::OCIAttrSet( (dvoid *)usrhpp, (ub4)OCI_HTYPE_SESSION, (dvoid *)pas.c_str(), (ub4)strlen(pas.c_str()), (ub4)OCI_ATTR_PASSWORD, errhpp);


/////////////////////////////////////////// 这里就失败了 ////////////////////////////////////////////////////////////
// 建立会话连接
if (::OCISessionBegin(svchpp, errhpp, usrhpp, OCI_CRED_RDBMS, (ub4)OCI_DEFAULT) != OCI_SUCCESS)
{
    int errcno;
    char errbuf[512] = {0};
    sb4 errcode;

    // 获取错误指针和 OCI 错误代码
    ::OCIErrorGet( (dvoid *)errhpp, (ub4)1, (text *)NULL, &errcode, (ub1 *)errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
    errcno = errcode;
    cout << "User session error:" << errbuf << endl;
    ::OCIHandleFree( (dvoid *)errhpp, OCI_HTYPE_ERROR);
    ::OCIHandleFree( (dvoid *)usrhpp, OCI_HTYPE_SESSION);
    ::OCIHandleFree( (dvoid *)svchpp, OCI_HTYPE_SVCCTX);
    ::OCIHandleFree( (dvoid *) servhpp, OCI_HTYPE_SERVER);
    return 1;//exit(1);
}

cout << "user session success!" << endl;

::OCIAttrSet( (dvoid *)svchpp, (ub4)OCI_HTYPE_SVCCTX, (dvoid *)usrhpp, (ub4)0, (ub4)OCI_HTYPE_SESSION, (OCIError *)errhpp);

// 执行 查询SQL语句
errhpp = NULL;

// 创建一个表达式句柄
if (::OCIHandleAlloc( (dvoid *)envhpp, (dvoid **)&stmthpp, OCI_HTYPE_STMT, (size_t)0, (dvoid **)0 ) != OCI_SUCCESS)
{
    cout << "Create STMT error!" << endl;
    return 1;//exit(1);
}
cout << "Create STMT success!" << endl;


// 创建错误句柄
::OCIHandleAlloc( (dvoid *)envhpp, (dvoid **)&errhpp, OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0);

// Select语句
char sql[255] = "select REALNAME, CODE from bpms_employee";
if (OCIStmtPrepare(stmthpp, errhpp, (text *)sql, (ub4)strlen(sql), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) != OCI_SUCCESS)
{
    cout << "Create prepare error!" << sql << endl;
    return 1;//exit(1);
}

cout << "Create prepare success!" << endl;

/// 绑定参数
// 申请绑定字段的句柄
OCIDefine *bhp1 = NULL;
OCIDefine *bhp2 = NULL;

// 存放数据的结构
struct result rst;

// 指定提取数据长度
ub2 datalen = 0;

// 定义指示器变量 , 用于取可能存在空值的字段
char isnul[6] = "";

// 定义输出变量 ,
OCIDefineByPos(stmthpp, &bhp1, errhpp, 1, (dvoid *)&rst.ename, sizeof(rst.ename), SQLT_CHR, NULL, &datalen, NULL, OCI_DEFAULT);
OCIDefineByPos(stmthpp, &bhp2, errhpp, 2, (dvoid *)&rst.cname, sizeof(rst.cname), SQLT_STR, NULL, &datalen, NULL, OCI_DEFAULT);

// 获取 SQL 语句类型
ub2 stmt_type;
OCIAttrGet ((dvoid *)stmthpp, (ub4)OCI_HTYPE_STMT, (dvoid *)&stmt_type, (ub4 *)0, (ub4)OCI_ATTR_STMT_TYPE, errhpp);

// 执行 SQL 语句
OCIStmtExecute(svchpp, stmthpp, errhpp, (ub4)0, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_DEFAULT);

// 获取查询信息
int rows_fetched;
do
{
    cerr << rst.ename<< " ";
    cerr << rst.cname<< " \n";
}
while(OCIStmtFetch2(stmthpp, errhpp, 1, OCI_FETCH_NEXT, 1, OCI_DEFAULT) != OCI_NO_DATA);

// 获得记录条数
OCIAttrGet((CONST void *)stmthpp, OCI_HTYPE_STMT, (void *)&rows_fetched, (ub4 *)sizeof(rows_fetched), OCI_ATTR_ROW_COUNT, errhpp);
cout << " rows :" << rows_fetched << endl;

// 执行 新增SQL 语句
if (OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&stmthpp, OCI_HTYPE_STMT, (size_t)0, (dvoid **)0) != OCI_SUCCESS)
{
    cout << "Create STMT error !" << endl;
    return 1;//exit(1);
}
cout << "Create stmt success !" << endl;

OCIHandleAlloc((dvoid *)envhpp, (dvoid **)&errhpp, OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0);

// Insert语句
char sql2[255] = "insert into table1 (col1, col2) values('testoci', 'testoci')";

// 准备Sql语句
if (OCIStmtPrepare(stmthpp, errhpp, (text *)sql2, (ub4)strlen(sql2), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) != OCI_SUCCESS)
{
    cout << "Create prepare error!" << sql2 << endl;
    return 1;//exit(1);
}
cout << "Create prepare success!" << endl;

// 执行SQL 语句
OCIStmtExecute(svchpp, stmthpp, errhpp, (ub4)1, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_DEFAULT);

// 断开用户会话
OCILogoff(svchpp, errhpp);

// 断开服务器连接
OCIServerDetach(servhpp, errhpp, OCI_DEFAULT);

// 释放资源
OCIHandleFree((dvoid *) stmthpp, OCI_HTYPE_STMT);
OCIHandleFree((dvoid *) svchpp, OCI_HTYPE_SVCCTX);
OCIHandleFree((dvoid *) servhpp, OCI_HTYPE_SERVER);
OCIHandleFree((dvoid *) errhpp, OCI_HTYPE_ERROR);

忘了一点,Oracle版本是11g

::OCIAttrSet( (dvoid *)svchpp, (ub4)OCI_HTYPE_SVCCTX, (dvoid *)usrhpp, (ub4)0, (ub4)OCI_HTYPE_SESSION, (OCIError *)errhpp);
这一段放到::OCISessionBegin 之前

// 设置属性
::OCIAttrSet( (dvoid *)svchpp, (ub4)OCI_HTYPE_SVCCTX, (dvoid *)servhpp, (ub4)0, (ub4)OCI_HTYPE_SERVER, (OCIError *)errhpp);

OCI_HTYPE_SERVER应该是OCI_ATTR_SERVER