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
需要使用OCI_STMT_SELECT == stmt_type ? 0 : 1, 0
6、中文乱码问题
OCIDefineByPos之后,需要设置编码如下:
注意:使用 OCIEnvNlsCreate设置 OCI_UTF16ID后,上面两个设置全部失败,代码必须使用Unicode(wchar_t)。注意是所有代码必须使用wchar_t。
完整代码下载地址:http://download.csdn.net/detail/ml232528/9623217
我将连接也放到了数据集中,是考虑到获取插入数据的自增id,多线程是安全的。注意大部分数据都返回为string(时间+数字+字符串),如果是数字,使用std::stoi等标准转换就可以,个人认为OCIDefineByPos太麻烦,这样就可以隐藏OCIDefineByPos的调用。如果有其它数据需要返回,你需要修改这个封装类。插入和更新也不使用绑定语法,自己使用sql语句吧,当然你也可以修改为bind语法,OCI_ATTR_STMT_TYPE可以方便的获取语句类型。ORACLE没有最后插入id的说法,你得使用sql语句来实现。每个OracleRecordSet有自己的连接,方便你实现最后插入id的获取。
官方文档http://docs.oracle.com/database/121/NLSPG/ch7progrunicode.htm#NLSPG0074
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; }
相关文章推荐
- svn的使用 方法OPTIONS失败与无法连接到服务器
- 使用Genymotion Android模拟器无法连接电脑本机的服务器
- 使用genymotion的时候 10.0.2.2无法连接电脑本机的服务器
- jdbc连接Oracle使用OCI方式产生EXCEPTION_ACCESS_VIOLATION 错误
- Oracle客户端无法连接服务器
- 在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连
- 在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接)
- 用WINXP2+DW+ACCESS使用本地 ASP.NET 和 ASP 服务器时数据库连接失败
- 局域网共享资源路径更改无法登陆问题(不允许一个用户使用一个以上用户名与一个服务器或共享资源的多重连接)解决
- 在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接)
- (转)在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: SQL 网络接口, error: 26 - 定位指定的服务器/实例时出错)
- MS SQL Server "无法连接到服务器,用户xxx登陆失败"
- 由于使用SVN 造成的项目无法使用的问题,报错“项目刷新失败,无法从服务器中检索文件夹信息 ”
- oracle提示 ORA-12154: TNS: 无法解析指定的连接标识符 OCIEnvCreate 失败, 返回代码为-1,但错误消息文本不可用
- 在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接
- 在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接
- 在端口 9081 的主机 CHQWEB 上启动传输失败。很可能是因为端口已被使用。请确保没有其它应用程序使用此端口,并重新启动服务器。com.ibm.ws.webcontainer.exception.TransportException: Failed
- 解决ASP.NET连接Oraclei数据库出现"无法加载DLL(oci.dll)"异常
- "无法连接到服务器,用户xxx登陆失败" 解决问题
- 在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接)