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