C++使用occi连接oracle数据库

什么是OCCI?

occi就是Oracle C++ Call Interface。

安装和使用

下载

去到oracle的官网,到下载页:https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html

在这里插入图片描述
然后网页往下拉,这个对应的sdk包就有相关头文件和使用例子等。
在这里插入图片描述

配项目属性

我把对应头文件和lib库放到了我的计算机的这里:
在这里插入图片描述
(1) 然后用使用的项目(VS2019下)属性配置相关的头文件引用和lib库引用,D:\usinglibs我配了环境变量LIBS_ROOT:
在这里插入图片描述
(2)静态库
在这里插入图片描述
在这里插入图片描述
debug版本的库一般是名字后面有一个d的。 oraocci19d.lib.

写代码

(1)DatabaseManager.h头文件

#pragma once
#include <Utils/ExportDefine.h>
#include <Utils/LogUtil.h>
#include <Utils/Config.h>
#include <occi.h>

using namespace utils;
using namespace oracle::occi;

namespace datacenter
{
    class DATACENTER_EXPORT DatabaseManager
    {
    public:
        DatabaseManager() {};
        ~DatabaseManager();
        //eg.connStr= "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.97)(PORT=1521))(CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = MyDb)))"
        int connect(const std::string& user, const std::string& passwd, const std::string& connStr);
        void getSecutityCodesFromDB(map<int, map<string, string> >& codeToNameMap, const string& sql, int date);
    private:
        //boost::shared_ptr<Environment> m_envPtr;
        //boost::shared_ptr<Connection> m_connPtr;
        Environment* m_envPtr;
        Connection* m_connPtr;
    };
}

(2)对应的cpp文件,DatabaseManager.cpp

#include <DataCenter\DatabaseManager.h>
using namespace datacenter;

DatabaseManager::~DatabaseManager()
{
    if (nullptr != m_connPtr)
    {
        m_envPtr->terminateConnection(m_connPtr);
        m_connPtr = nullptr;
    }
    if (nullptr != m_envPtr)
    {
        Environment::terminateEnvironment(m_envPtr);
        m_envPtr = nullptr;
    }
}

int DatabaseManager::connect(const std::string& user, const std::string& passwd,
    const std::string& connStr)
{
    try
    {
        m_envPtr = /*boost::shared_ptr<Environment>(*/Environment::createEnvironment("ZHS16GBK","ZHS16GBK");
        m_connPtr = /*boost::shared_ptr<Connection>(*/m_envPtr->createConnection(user, passwd, connStr);
    }
    catch (SQLException& e)
    {
        LLogError("Using " << user << "/" << passwd << "@" << connStr << " connect to database error," << e.getErrorCode() << ": " << e.getMessage());
        return -1;
    }
    return 0;
}

void DatabaseManager::getSecutityCodesFromDB(map<int, map<string,string> >& codeToNameMap, const string& sql, int date)
{
    try
    {
        Statement* stmt = m_connPtr->createStatement();
        ResultSet* rs = stmt->executeQuery(sql);
        while (rs->next() != 0)
        {
            codeToNameMap[date][rs->getString(1)] = rs->getString(2);
        }
        LLogInfo("Secutity codes,date:" << date << ",nums:" << codeToNameMap[date].size());
        stmt->closeResultSet(rs);
        m_connPtr->terminateStatement(stmt);
    }
    catch (SQLException& e)
    {
        LLogError("Error," << e.getErrorCode() << ": " << e.getMessage());
    }

}

(3)某个使用的cpp中

void DbData::initCodeToNameMap(int startDate, int endDate)
{
    Configuration cfg(m_configFile);
    cfg.load();
    string user = cfg.read("oracle", "userName");
    string pwd = cfg.read("oracle", "password");
    string host = cfg.read("oracle", "host");
    string port = cfg.read("oracle", "port");
    string db = cfg.read("oracle", "serviceName");
    string stypes = cfg.read("oracle", "stype");
    string exchanges = cfg.read("oracle", "exchange");
    string connStr = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=" + host + ")(PORT=" + port + "))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=" + db + ")))";
    LLogInfo("Read Config, userName:" << user << ",password:" << pwd << ",host:" << host << ",port:" << port << ",serviceName:" << db << ",stype:" << stypes << ",exchange:" << exchanges);
    datacenter::DatabaseManager dbMan = datacenter::DatabaseManager();
    if (dbMan.connect(user, pwd, connStr) != 0)
    {
        return;
    }
    m_codeToNameMap.clear();
    stringstream ss;
    int nowdate = startDate;
    LLogInfo("Get data from date:" << startDate << " to date:" << endDate);
    vector<string> stypeVec = cfg.readVector("oracle", "stype", ",");
    vector<string> exchangeVec = cfg.readVector("oracle", "exchange", ",");
    stringstream sstype;
    stringstream sexchange;
    addSingleQuotes(sstype, stypeVec);
    addSingleQuotes(sexchange, exchangeVec);
    while (nowdate < endDate)
    {
        ss << nowdate;
        string date = ss.str();
        ss.clear();//情况状态
        ss.str("");//清空缓存
        string sql = "select symbol,sname from securitycode where stype in (" + sstype.str() + ") and exchange in (" + sexchange.str() + ") and status = 0 and enabled=0 and to_char(ListDate,'YYYYMMDD') <='" + date + "'";
        dbMan.getSecutityCodesFromDB(m_codeToNameMap, sql, nowdate);
        nowdate = utils::nextDate(nowdate);
    }
}

注意:本人的代码因为是实际使用的,如日志库和配置文件读取等上面的代码用并没有。想要编译通过,需要注释掉。

遇到的问题

(1)对应的动态库放到运行目录下,不单单是oraocci19d.dll这个库,还需要如下两个,否则运行数据库连接的时候,会抛出异常,连接不成功。
oraociei19.dll
oraons.dll
(2)sql语句后面不需要分号;,注意看我的代码,否则也会出错抛异常。

(3)下载occi的时候请自行根据自己的vs版本下相应的版本,如果你vs版本低,occi的版本也要跟着用低的。
在这里插入图片描述
之前看官网这里说要求是vs2017,以为2019不行,实践证明其实也是可以的。

完毕。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值