您的位置:首页 > 数据库 > Oracle

ORACLE连接服务器失败,无法使用oci连接其它电脑的 ORACLE服务器等,oci 接口c++封装。

2016-09-02 13:33 1266 查看
0、下载sdk

oci的sdk不需要安装,绿色版本。
http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html
1、本地连接服务失败

不能使用sys这个用户连接服务器。请使用其它用户连接服务器。还有创建完数据库后,一定要重启下电脑,不然都是扯淡的。
https://localhost:5500/em/login 可以使用这个网页登录一下看看用户什么的。

2、其它电脑连接服务失败。

使用netstat -an 看看1521端口(ORACLE服务的监听端口,如果没有修改的话)是不是0.0.0.0:1521,如果不是那么服务器需要修改。

使用ORACLE Net Manager,监听程序网络地址那里, 将主机名修改为0.0.0.0重启服务就行了(重启服务命令Lsnrctl stop->Lsnrctl
start)。

修改最终体现在

product\12.1.0\dbhome_1\NETWORK\ADMIN\listener.ora文件中,

LISTENER =

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST = 0.0.0.0)(PORT = 1521))

  )

3、OCIServerAttach 连接服务失败问题:

错误代码:ORA-12504: TNS:listener was not given the SERVICE_NAME in CONNECT_DATA

OCIServerAttach中const OraText *dblink参数串格式应该是:192.168.1.164:1521/orcl。上面的错误说明“/orcl”没有添加上。orcl是服务名,192.168.1.164:1521是ip和端口。也可以使用OCIAttrSet设置这些属性。

4、OCISessionBegin错误:ORA-28547:connection to server failed,probable oracle net admin error

用32位sdk连接64位ORACLE出现这个错误,后来我用64位sdk连接成功后。32位和64位sdk连接都没有问题了,然后一脸懵逼。

5、OCIStmtExecute插入数据失败ORA-24333: zero iteration count

// 获取 SQL 语句类型
ub2 stmt_type = 0;
OCIAttrGet(stmthp_, OCI_HTYPE_STMT, &stmt_type, nullptr, OCI_ATTR_STMT_TYPE, errhp_);

ret = OCIStmtExecute(svchp_, stmthp_, errhp_, OCI_STMT_SELECT == stmt_type ? 0 : 1, 0,nullptr, nullptr, OCI_DEFAULT);
if (OCI_SUCCESS != ret)
{
OraText errbuf[512] = {};
sb4 errcode = 0;
OCIErrorGet(errhp_, 1, nullptr, &errcode, errbuf, sizeof(errbuf), OCI_HTYPE_ERROR);
return false;
}


需要使用OCI_STMT_SELECT == stmt_type ? 0 : 1, 0 

6、中文乱码问题

OCIDefineByPos之后,需要设置编码如下:

{
OraText t[] = "ZHS16GBK";
ub2 id = OCINlsCharSetNameToId(connection_.envhp_, t);
ret = OCIAttrSet(dfnhp, OCI_HTYPE_DEFINE, &id, 0, OCI_ATTR_CHARSET_ID, errhp_);
if (OCI_SUCCESS != ret)
{
return false;
}
}



同样插入语句如果有中文需要设置编码如下:

OCIBindByName(stmthp1, &bnd1p, errhp, (oratext*)":ENAME",
(sb4)strlen((char *)":ENAME"), (void *) ename, sizeof(ename),
SQLT_STR, (void *)&insname_ind, (ub2 *) 0, (ub2 *) 0, (ub4) 0,
(ub4 *)0, OCI_DEFAULT);
OCIAttrSet((void *) bnd1p, (ub4) OCI_HTYPE_BIND, (void *) &id,
(ub4) 0, (ub4)OCI_ATTR_CHARSET_ID, errhp);
OCIAttrSet((void *) bnd1p, (ub4) OCI_HTYPE_BIND, (void *) &ename_col_len,
(ub4) 0, (ub4)OCI_ATTR_MAXDATA_SIZE, errhp);
 OCINlsCharSetNameToId可以获取到编码id,OCIAttrSet使用参数OCI_ATTR_CHARSET_ID设置id。

注意:使用 OCIEnvNlsCreate设置 OCI_UTF16ID后,上面两个设置全部失败,代码必须使用Unicode(wchar_t)。注意是所有代码必须使用wchar_t。
auto ret = OCIEnvNlsCreate(&envhp_, OCI_DEFAULT, nullptr, nullptr, nullptr, nullptr, 0, nullptr, OCI_UTF16ID, OCI_UTF16ID);
使用Unicode,注意一下有些地方需要strDbAddr.length() *2。比如:
ret = OCIServerAttach(srvhp_, errhp_
, reinterpret_cast<OraText const *>(strDbAddr.c_str()), strDbAddr.length() * 2, OCI_DEFAULT);



7、c++封装代码(用到了一些c++11语法)

完整代码下载地址:http://download.csdn.net/detail/ml232528/9623217

我将连接也放到了数据集中,是考虑到获取插入数据的自增id,多线程是安全的。注意大部分数据都返回为string(时间+数字+字符串),如果是数字,使用std::stoi等标准转换就可以,个人认为OCIDefineByPos太麻烦,这样就可以隐藏OCIDefineByPos的调用。如果有其它数据需要返回,你需要修改这个封装类。插入和更新也不使用绑定语法,自己使用sql语句吧,当然你也可以修改为bind语法,OCI_ATTR_STMT_TYPE可以方便的获取语句类型ORACLE没有最后插入id的说法,你得使用sql语句来实现。每个OracleRecordSet有自己的连接,方便你实现最后插入id的获取。


关于为何使用OCI_UTF16ID,是因为中文乱码问题,很难解决。 OCIAttrSet(dfnhp, OCI_HTYPE_DEFINE, &id, 0, OCI_ATTR_CHARSET_ID,
errhp_);可以解决查询结果为中文乱码问题,但是执行语句有中文就不能解决了。除非使用绑定语法,将所有中文使用OCIBindBy*函数然后设置OCI_ATTR_CHARSET_ID。对于中文乱码测试发现OCI_ATTR_ENV_NLS_LANGUAGE的修改设置没有作用。

官方文档http://docs.oracle.com/database/121/NLSPG/ch7progrunicode.htm#NLSPG0074


main.cpp

#include "stdafx.h"
#include "OracleRecordSet.h"
#include <algorithm>

int main()
{
g_conOracle.Connect(L"127.0.0.1", 1521, L"C##k", L"k", L"orcl");

{
COracleRecordSet re(g_conOracle);

if (!re.Execute(L"Insert into TESTTAB (ID,USERNAME__TEST_______TEST___) values (TESTTAB_ID.NEXTVAL,'你好啊')"))
{
return 0;
}

if (!re.Execute(L"select * from TESTTAB"))
{
return 0;
}
std::vector<std::wstring> listValue;
auto nCount = re.GetCurPos();
while (re.MoveNext())
{
nCount = re.GetCurPos();
for (int i = 0; i != 16 ; i++)
{
listValue.push_back(re.GetValueStringByPos(i));
}

listValue.push_back(re.GetValueStringByName(L"charTest"));
}
}

g_conOracle.DisConnect();
return 0;
}



文件:OracleRecordSet.h


#pragma once
#include <string>
#include <memory>
#include <tuple>

#ifndef _WIN64
#include "OCI\X86\include\oci.h"
#include "OCI\X86\include\occi.h"
#pragma comment(lib,"OCI\\X86\\lib\\MSVC\\oci.lib")
#else
#include "OCI\X64\include\oci.h"
#include "OCI\X64\include\occi.h"
#pragma comment(lib,"OCI\\X64\\lib\\MSVC\\oci.lib")
#endif

class COracleRecordSet;
class COracleConnection
{
public:
COracleConnection();
~COracleConnection();
public:
bool Connect(std::wstring const &strIp,int nPort,std::wstring const &strUserName,std::wstring const &strPassWord,std::wstring const &strDbName);
bool IsConnect();
void DisConnect();
private:
OCIEnv  *envhp_ = nullptr;
OCIServer *srvhp_ = nullptr;
OCIError *errhp_ = nullptr;
bool bConnect_ = false;
std::wstring strUserName_;
std::wstring strPassWord_;
std::wstring strDbName_;
friend COracleRecordSet;
};

class COracleRecordSet
{
public:
COracleRecordSet(COracleConnection &);
~COracleRecordSet();
public:
bool Init();
void Free();
void DisConnect();
bool Connect();
public:
bool Execute(std::wstring const &strSql);
int GetCurPos();
bool MoveNext();
std::wstring GetValueStringByName(std::wstring const &strName);
std::wstring GetValueStringByPos(int nPos);
private:
std::wstring ValueItemToString(std::tuple<std::shared_ptr<wchar_t>, int, int, std::wstring> const &pItem);
private:
COracleConnection &connection_;
OCIError *errhp_ = nullptr;
OCIStmt *stmthp_ = nullptr;
OCISvcCtx *svchp_ = nullptr;
OCISession *usrhp_ = nullptr;// 初始化会话句柄
bool bConnect_ = false;
bool bInit_ = false;
std::vector<std::tuple<std::shared_ptr<wchar_t>,int, int,std::wstring>> listSelectRet_;
};

extern COracleConnection g_conOracle;</span>
源文件:OracleRecordSet.cpp


#include "stdafx.h"
#include "OracleRecordSet.h"
#include <cassert>
#include <algorithm>

COracleConnection g_conOracle;

COracleConnection::COracleConnection()
{

}

COracleConnection::~COracleConnection()
{
DisConnect();
}

bool COracleConnection::Connect(std::wstring const & strIp, int nPort, std::wstring const & strUserName, std::wstring const & strPassWord, std::wstring const & strDbName)
{
if (bConnect_)
{
return false;
}

bConnect_ = true;

OCISvcCtx *svchp = nullptr;
OCISession *usrhp = nullptr;// 初始化会话句柄
strUserName_ = strUserName;
strPassWord_ = strPassWord;
strDbName_ = strDbName;

auto ret = OCIEnvNlsCreate(&envhp_, OCI_DEFAULT, nullptr, nullptr, nullptr, nullptr, 0, nullptr, OCI_UTF16ID, OCI_UTF16ID);
if (OCI_SUCCESS != ret)
{
goto errEnvCreate;
}

ret = OCIHandleAlloc(envhp_, (reinterpret_cast<void **>(&errhp_)), OCI_HTYPE_ERROR, 0, nullptr);
if (OCI_SUCCESS != ret)
{
goto errAllocErrhp;
}

ret = OCIHandleAlloc(envhp_, (reinterpret_cast<void **>(&srvhp_)), OCI_HTYPE_SERVER, 0, nullptr);
if (OCI_SUCCESS != ret)
{
goto errAllocSrvhp;
}

//{

//OraText tb[OCI_NLS_MAXBUFSZ] = {};
//OCINlsGetInfo(envhp_, errhp_, tb, sizeof(tb),
//	OCI_NLS_CHARACTER_SET);

//	{
//		//OraText t[100] = "SIMPLIFIED CHINESE_CHINA.ZHS16GBK";
//		OraText t[100] = "ZHS16GBK";
//		ub2 id = OCINlsCharSetNameToId(envhp_, t);
//		//assert(0);
//	}

//	OraText   infoBuf2[OCI_NLS_MAXBUFSZ] = { "SIMPLIFIED CHINESE_CHINA.ZHS16GBK" };
//	//OraText   infoBuf2[OCI_NLS_MAXBUFSZ] = { "SIMPLIFIED CHINESE_CHINA.ZHS16GBK" };
//	ub4 infoSize = sizeof(infoBuf2);
//	OCIAttrSet(envhp_, OCI_HTYPE_ENV, infoBuf2, infoSize, OCI_ATTR_ENV_NLS_LANGUAGE, errhp_);
//	if (OCI_SUCCESS != ret)
//	{
//		assert(0);
//	}

//	OCIAttrGet(envhp_, OCI_HTYPE_ENV, infoBuf2, &infoSize, OCI_ATTR_ENV_NLS_LANGUAGE, errhp_);
//	if (OCI_SUCCESS != ret)
//	{
//		assert(0);
//	}
//}

ret = OCIHandleAlloc(envhp_, reinterpret_cast<void **>(&svchp), OCI_HTYPE_SVCCTX,0,nullptr);
if (OCI_SUCCESS != ret)
{
goto errAllocsvchp;
}

ret = OCIHandleAlloc(envhp_, reinterpret_cast<void **>(&usrhp), OCI_HTYPE_SESSION, 0, nullptr);
if (OCI_SUCCESS != ret)
{
goto errAllocusrhp;
}

{
std::wstring strDbAddr = strIp + L":" + std::to_wstring(nPort);
if (!strDbName.empty())
{
strDbAddr += L"/" + strDbName;
}
ret = OCIServerAttach(srvhp_, errhp_
, reinterpret_cast<OraText const *>(strDbAddr.c_str()), strDbAddr.length() * (sizeof(strDbAddr[0]) / sizeof(OraText)), OCI_DEFAULT);
if (OCI_SUCCESS != ret)
{
OraText errbuf[512] = {};
sb4 errcode = 0;
OCIErrorGet(errhp_, 1, nullptr, &errcode, errbuf, sizeof(errbuf), OCI_HTYPE_ERROR);
goto errServerAttach;
}
}

ret = OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, srvhp_, 0, OCI_ATTR_SERVER, errhp_);
if (OCI_SUCCESS != ret)
{
goto errAttrSetSvchpSrvhp;
}

// 设置用户名、密码
ret = OCIAttrSet(usrhp, OCI_HTYPE_SESSION, const_cast<wchar_t *>(strUserName.c_str()), strUserName.length() * sizeof(wchar_t), OCI_ATTR_USERNAME, errhp_);
if (OCI_SUCCESS != ret)
{
goto errSetUserName;
}

ret = OCIAttrSet(usrhp,OCI_HTYPE_SESSION, const_cast<wchar_t *>(strPassWord.c_str()), strPassWord.length() * sizeof(wchar_t), OCI_ATTR_PASSWORD, errhp_);

if (OCI_SUCCESS != ret)
{
goto errSetPassword;
}

ret = OCISessionBegin(svchp, errhp_, usrhp, OCI_CRED_RDBMS,OCI_DEFAULT);
if (OCI_SUCCESS != ret)
{
OraText errbuf[512] = {};
sb4 errcode = 0;
OCIErrorGet(errhp_, 1, nullptr, &errcode, errbuf, sizeof(errbuf), OCI_HTYPE_ERROR);
goto errSessionBegin;
}

OCIAttrSet(svchp, OCI_HTYPE_SVCCTX,usrhp,	0, OCI_ATTR_SESSION, errhp_);
OCISessionEnd(svchp, errhp_, usrhp, OCI_DEFAULT);
OCIHandleFree(usrhp, OCI_HTYPE_SESSION);
usrhp = nullptr;
OCIHandleFree(svchp, OCI_HTYPE_SVCCTX);
svchp = nullptr;

return true;
errSessionBegin:
errSetPassword:
errSetUserName:
errAttrSetSvchpSrvhp:
OCIServerDetach(srvhp_, errhp_, OCI_DEFAULT);
errServerAttach:
OCIHandleFree(usrhp, OCI_HTYPE_SESSION);
usrhp = nullptr;
errAllocusrhp:
OCIHandleFree(svchp, OCI_HTYPE_SVCCTX);
svchp = nullptr;
errAllocsvchp:
OCIHandleFree(srvhp_, OCI_HTYPE_ERROR);
errhp_ = nullptr;
errAllocSrvhp:
OCIHandleFree(errhp_, OCI_HTYPE_SERVER);
srvhp_ = nullptr;
errAllocErrhp:
OCIHandleFree(envhp_, OCI_HTYPE_ENV);
envhp_ = nullptr;
errEnvCreate:
bConnect_ = false;
return false;
}

bool COracleConnection::IsConnect()
{
return bConnect_;
}

void COracleConnection::DisConnect()
{
if (!bConnect_)
{
return;
}

bConnect_ = false;

OCIServerDetach(srvhp_, errhp_, OCI_DEFAULT);

OCIHandleFree(errhp_, OCI_HTYPE_ERROR);
envhp_ = nullptr;
OCIHandleFree(srvhp_, OCI_HTYPE_SERVER);
srvhp_ = nullptr;
OCIHandleFree(envhp_, OCI_HTYPE_ENV);
envhp_ = nullptr;
}

COracleRecordSet::COracleRecordSet(COracleConnection & con)
:connection_(con)
{

}

COracleRecordSet::~COracleRecordSet()
{
DisConnect();
Free();
}

bool COracleRecordSet::Execute(std::wstring const & strSql)
{
//使用自增字段的第二种方法,在插入一条记录后马上执行一下下面的语句即返回当前插入数据的ID。
//	$query = "select seq_atable.currval from dual";
//seq_atable.currval 的值只有在同一次会话中,发生seq_atable.nextval后有效:) 所以不会存在取错值的问题。

if (!Init())
{
return false;
}

if (!Connect())
{
return false;
}

listSelectRet_.clear();

auto ret = OCIStmtPrepare(stmthp_, errhp_, reinterpret_cast<OraText const *>(strSql.c_str())
, strSql.length() * (sizeof(wchar_t) / sizeof(OraText)), OCI_NTV_SYNTAX, OCI_DEFAULT);

if (OCI_SUCCESS != ret)
{
return false;
}

// 获取 SQL 语句类型
ub2 stmt_type = 0;
OCIAttrGet(stmthp_, OCI_HTYPE_STMT, &stmt_type, nullptr, OCI_ATTR_STMT_TYPE, errhp_);

ret = OCIStmtExecute(svchp_, stmthp_, errhp_, stmt_type == OCI_STMT_SELECT ? 0 : 1, 0,nullptr, nullptr, OCI_DEFAULT);
if (OCI_SUCCESS != ret)
{
OraText errbuf[512] = {};
sb4 errcode = 0;
OCIErrorGet(errhp_, 1, nullptr, &errcode, errbuf, sizeof(errbuf), OCI_HTYPE_ERROR);
return false;
}

if (stmt_type == OCI_STMT_SELECT)  //查询
{
ub4 fieldCount = 0;
OCIAttrGet(stmthp_, OCI_HTYPE_STMT, &fieldCount, nullptr, OCI_ATTR_PARAM_COUNT, errhp_);

if (OCI_SUCCESS != ret)
{
return false;
}

for (ub4 i = 0; i != fieldCount; i++)
{
OCIParam  *mypard = nullptr;
ub4        dtype = 0;

ub4 dtypeSize = sizeof(dtype);
ret = OCIParamGet(stmthp_, OCI_HTYPE_STMT, errhp_, reinterpret_cast<void **>(&mypard), i + 1);

if (OCI_SUCCESS != ret)
{
return false;
}

ret = OCIAttrGet(mypard, OCI_DTYPE_PARAM, &dtype, &dtypeSize, OCI_ATTR_DATA_TYPE, errhp_);
if (OCI_SUCCESS != ret)
{
return false;
}

OraText *colName;
ub4 colNameSize = sizeof(colName);
ret = OCIAttrGet(mypard, OCI_DTYPE_PARAM, &colName, &colNameSize, OCI_ATTR_NAME, errhp_);
if (OCI_SUCCESS != ret)
{
return false;
}

ub4   col_len = 200;
ub4   col_lenSize = sizeof(col_len);
auto dtypeNew = SQLT_CHR;
switch (dtype)
{
case SQLT_DAT:
case SQLT_DATE:
case SQLT_TIME:
case SQLT_TIME_TZ:
case SQLT_TIMESTAMP:
case SQLT_TIMESTAMP_TZ:
case SQLT_TIMESTAMP_LTZ:
{
dtypeNew = SQLT_ODT;
col_len = sizeof(OCIDate);
}
break;
//case SQLT_BLOB:
case SQLT_CLOB:
//case SQLT_BFILEE:
{
ret = OCIAttrGet(mypard, OCI_DTYPE_PARAM, &col_len, &col_lenSize, OCI_ATTR_DATA_SIZE, errhp_);
if (OCI_SUCCESS != ret)
{
return false;
}
}
break;
case SQLT_CHR:
case SQLT_INT:
case SQLT_NUM:
case SQLT_FLT:
case SQLT_STR:
case SQLT_VNU:
case SQLT_LNG:
case SQLT_VCS:
case SQLT_LVC:
case SQLT_AFC:
case SQLT_AVC:
{
ret = OCIAttrGet(mypard, OCI_DTYPE_PARAM, &col_len, &col_lenSize, OCI_ATTR_DATA_SIZE, errhp_);
if (OCI_SUCCESS != ret)
{
return false;
}
if (col_len < 200)
{
col_len = 200;
}
dtypeNew = SQLT_CHR;
}
break;
default:
assert(0);
break;
}

wchar_t *pBuffer = nullptr;
try
{
pBuffer = new wchar_t[col_len];
memset(pBuffer, 0, col_len);
}
catch (const std::exception&)
{
return false;
}
std::tuple<std::shared_ptr<wchar_t>,int, int,std::wstring> pItem;
std::get<0>(pItem) = std::shared_ptr<wchar_t>(pBuffer, [](wchar_t *p) {delete[] p;});
std::get<1>(pItem) = col_len;
std::get<2>(pItem) = dtypeNew;
std::get<3>(pItem).append(reinterpret_cast<wchar_t*>(colName), colNameSize);
listSelectRet_.push_back(pItem);

OCIDefine *dfnhp = nullptr;

ret = OCIDefineByPos(stmthp_, &dfnhp, errhp_, i + 1, pBuffer, col_len * sizeof(wchar_t), dtypeNew, 0, 0, 0, OCI_DEFAULT);
if (OCI_SUCCESS != ret)
{
return false;
}

//解决中文乱码问题
//{
//	//OraText t[100] = "SIMPLIFIED CHINESE_CHINA.ZHS16GBK";
//	OraText t[100] = "ZHS16GBK";
//	ub2 id = OCINlsCharSetNameToId(connection_.envhp_, t);
//	ub2 id2 = 0;
//	ub4 nSizeId2 = sizeof(id2);
//	ret = OCIAttrGet(dfnhp, OCI_HTYPE_DEFINE, &id2, &nSizeId2, OCI_ATTR_CHARSET_ID, errhp_);
//	ret = OCIAttrSet(dfnhp, OCI_HTYPE_DEFINE, &id, 0, OCI_ATTR_CHARSET_ID, errhp_);
//	if (OCI_SUCCESS != ret)
//	{
//		return false;
//	}
//}

}
}

return true;
}

bool COracleRecordSet::Init()
{
if (bInit_) return true;
bInit_ = true;

if (!connection_.IsConnect())
{
assert(0);
goto errIsConnect;
}

auto ret = OCIHandleAlloc(connection_.envhp_, reinterpret_cast<void **>(&errhp_), OCI_HTYPE_ERROR, 0, nullptr);
if (OCI_SUCCESS != ret)
{
goto errAllocerrhp;
}

ret = OCIHandleAlloc(connection_.envhp_, reinterpret_cast<void **>(&svchp_), OCI_HTYPE_SVCCTX, 0, nullptr);
if (OCI_SUCCESS != ret)
{
goto errAllocsvchp;
}

// 创建用户连接句柄
ret = OCIHandleAlloc(connection_.envhp_, reinterpret_cast<void **>(&usrhp_), OCI_HTYPE_SESSION, 0, nullptr);
if (OCI_SUCCESS != ret)
{
goto errAllocusrhp;
}

ret = OCIHandleAlloc(connection_.envhp_, reinterpret_cast<void **>(&stmthp_), OCI_HTYPE_STMT, 0, nullptr);
if (OCI_SUCCESS != ret)
{
goto errAllocStmthp;
}

return true;
errAllocStmthp:
OCIHandleFree(usrhp_, OCI_HTYPE_SESSION);
usrhp_ = nullptr;
errAllocusrhp:
OCIHandleFree(svchp_, OCI_HTYPE_SVCCTX);
svchp_ = nullptr;
errAllocsvchp:
OCIHandleFree(errhp_, OCI_HTYPE_ERROR);
errhp_ = nullptr;
errAllocerrhp:
errIsConnect:
bInit_ = false;
return false;
}

void COracleRecordSet::Free()
{
if (!bInit_) return;
bInit_ = false;
OCIHandleFree(svchp_, OCI_HTYPE_SVCCTX);
svchp_ = nullptr;
OCIHandleFree(usrhp_, OCI_HTYPE_SESSION);
usrhp_ = nullptr;
OCIHandleFree(stmthp_, OCI_HTYPE_STMT);
stmthp_ = nullptr;
OCIHandleFree(errhp_, OCI_HTYPE_ERROR);
errhp_ = nullptr;
}

void COracleRecordSet::DisConnect()
{
if (!bConnect_) return;
bConnect_ = false;
OCISessionEnd(svchp_, errhp_, usrhp_, OCI_DEFAULT);
}

bool COracleRecordSet::Connect()
{
if (bConnect_) return true;

assert(bInit_);

bConnect_ = true;

auto ret = OCIAttrSet(svchp_, OCI_HTYPE_SVCCTX, connection_.srvhp_, 0, OCI_ATTR_SERVER, errhp_);

if (OCI_SUCCESS != ret)
{
goto errAttrSetSvchpSrvhp;
}

// 设置用户名、密码
ret = OCIAttrSet(usrhp_, OCI_HTYPE_SESSION, const_cast<wchar_t *>(connection_.strUserName_.c_str()), connection_.strUserName_.length() * sizeof(connection_.strUserName_[0]), OCI_ATTR_USERNAME, errhp_);
if (OCI_SUCCESS != ret)
{
goto errSetUserName;
}

ret = OCIAttrSet(usrhp_, OCI_HTYPE_SESSION, const_cast<wchar_t *>(connection_.strPassWord_.c_str()), connection_.strPassWord_.length() * sizeof(connection_.strUserName_[0]), OCI_ATTR_PASSWORD, errhp_);

if (OCI_SUCCESS != ret)
{
goto errSetPassword;
}

ret = OCIAttrSet(svchp_, OCI_HTYPE_SVCCTX, connection_.srvhp_, 0, OCI_ATTR_SERVER, errhp_);

if (OCI_SUCCESS != ret)
{
goto errAttrSetSvchpSrvhp;
}

ret = OCISessionBegin(svchp_, errhp_, usrhp_, OCI_CRED_RDBMS, OCI_DEFAULT);
if (OCI_SUCCESS != ret)
{
goto errSessionBegin;
}

ret = OCIAttrSet(svchp_, OCI_HTYPE_SVCCTX, usrhp_, 0, OCI_ATTR_SESSION, errhp_);
if (OCI_SUCCESS != ret)
{
goto errSessionBegin;
}
return true;

errSessionBegin:
errSetPassword:
errSetUserName:
errAttrSetSvchpSrvhp:
bConnect_ = false;
return false;
}

int COracleRecordSet::GetCurPos()
{
//下面这个获取的是OCIStmtFetch调用的次数,不是结果行数
int rows_fetched = 0;
ub4 nSize = sizeof(rows_fetched);
auto ret = OCIAttrGet(stmthp_, OCI_HTYPE_STMT, &rows_fetched, &nSize, OCI_ATTR_ROW_COUNT, errhp_);
return rows_fetched;
}

bool COracleRecordSet::MoveNext()
{
auto ret = OCIStmtFetch(stmthp_, errhp_, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
if (OCI_NO_DATA == ret)
{
OraText errbuf[512] = {};
sb4 errcode = 0;
OCIErrorGet(errhp_, 1, nullptr, &errcode, errbuf, sizeof(errbuf), OCI_HTYPE_ERROR);
return false;
}
return true;
}
std::wstring COracleRecordSet::ValueItemToString(std::tuple<std::shared_ptr<wchar_t>, int, int, std::wstring> const &pItem)
{
std::wstring strVal;
switch (std::get<2>(pItem))
{
case SQLT_CHR:  //wchar_t

{
strVal.append(std::get<0>(pItem).get(), std::get<1>(pItem));
}
break;
case SQLT_STR:  //wchar_t[n + 1]
{
strVal.append(std::get<0>(pItem).get(), std::get<1>(pItem));
}
break;
case SQLT_ODT:
{
OCIDate *pDate = reinterpret_cast<OCIDate *>(std::get<0>(pItem).get());
sb2 yr = 0; ub1 mnth = 0; ub1 dy = 0;
ub1 hr = 0, mm = 0, ss = 0;
OCIDateGetDate(pDate, &yr, &mnth, &dy);
OCIDateGetTime(pDate, &hr, &mm, &ss);
wchar_t szTime[256] = {};
//sprintf_s(szTime, "%04d-%02d-%02d %02d:%02d:%02d", yr, mnth, dy, hr, mm, ss);
swprintf_s(szTime, L"%04d-%02d-%02d %02d:%02d:%02d", yr, mnth, dy, hr, mm, ss);
strVal = szTime;
break;
}
break;
case SQLT_DATE:  //OCIDateTime *
case SQLT_TIMESTAMP:   //OCIDateTime *
case SQLT_TIMESTAMP_TZ:  //OCIDateTime *
case SQLT_TIMESTAMP_LTZ: //OCIDateTime *
{
assert(0);
OCIDateTime *pData = reinterpret_cast<OCIDateTime *>(std::get<0>(pItem).get());
sb2 yr=0; ub1 mnth=0; ub1 dy=0;
ub1 hr = 0, mm = 0, ss = 0;
ub4 fsec = 0;
auto ret = OCIDateTimeGetDate(usrhp_, errhp_, pData, &yr, &mnth, &dy); //第一个参数 The OCI user session handle or environment handle.
if (OCI_SUCCESS != ret)
{
break;
}
ret = OCIDateTimeGetTime(usrhp_, errhp_, pData,&hr,&mm,&ss,&fsec);
if (OCI_SUCCESS != ret)
{
break;
}
wchar_t szTime[256] = {};
swprintf_s(szTime,L"%04d-%02d-%02d %02d:%02d:%02d", yr, mnth, dy, hr, mm, ss);
strVal = szTime;
}
break;
case SQLT_INTERVAL_DS: //OCIInterval
{

}
break;
case SQLT_INT:  //signed wchar_t,signed int ,signed short ...
{
long nValue = 0;
if (std::get<1>(pItem) <= sizeof(nValue))
{
memcpy(&nValue, std::get<0>(pItem).get(), std::get<1>(pItem));
strVal = std::to_wstring(nValue);
}
else
{
assert(0);
}
}
break;
case SQLT_UIN:  //unsigned
{
unsigned nValue = 0;
if (std::get<1>(pItem) <= sizeof(nValue))
{
memcpy(&nValue, std::get<0>(pItem).get(), std::get<1>(pItem));
strVal = std::to_wstring(nValue);
}
else
{
assert(0);
}
}
break;
case SQLT_FLT:  //float,double
{
double dValue = 0.0;
if (std::get<1>(pItem) <= sizeof(dValue))
{
memcpy(&dValue, std::get<0>(pItem).get(), std::get<1>(pItem));
strVal = std::to_wstring(dValue);
}
else
{
assert(0);
}
}
break;
case SQLT_PDN:
break;
case SQLT_BIN:  //unsigned wchar_t

{
strVal.append(std::get<0>(pItem).get(), std::get<1>(pItem));
}
break;
case SQLT_NUM:  // unsigned wchar_t
{
strVal.append(std::get<0>(pItem).get(), std::get<1>(pItem));
}
break;
case SQLT_NTY:  //struct
break;
case SQLT_REF:  //OCIRef
{

}
break;
case SQLT_VST:  //OCIString
{

}
break;
case SQLT_VNU:  //wchar_t[22]
{
strVal.append(std::get<0>(pItem).get(), std::get<1>(pItem));
}
break;
assert(0);
default:
break;
}

return strVal;
}

std::wstring COracleRecordSet::GetValueStringByName(std::wstring const & strName)
{
std::wstring strValue;
std::wstring strNameUp = strName;

std::transform(strNameUp.begin(), strNameUp.end(), strNameUp.begin(), toupper); //比较忽略大小写
for (auto const &item : listSelectRet_)
{
std::wstring strNameItemUp = std::get<3>(item);
std::transform(strNameItemUp.begin(), strNameItemUp.end(), strNameItemUp.begin(), toupper); //比较忽略大小写
if (strNameItemUp == strNameUp)
{
strValue = ValueItemToString(item);
//strValue.append(std::get<0>(item).get(), std::get<1>(item));
break;
}
}

return strValue;
}

std::wstring COracleRecordSet::GetValueStringByPos(int nPos)
{
std::wstring strValue;
if (listSelectRet_.size() <= static_cast<unsigned int>(nPos))
{
return strValue;
}

auto it = listSelectRet_.begin();
std::advance(it, nPos);
auto item = *it;
strValue = ValueItemToString(item);
return strValue;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  oci ORACLE 连接 封装
相关文章推荐