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

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[n]
	{
		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[n]
	{
		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;
}



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值