oci批量提取oracle数据写入mongodb或写成bson文件
2018-01-19 12:09
288 查看
项目需要,将oracle中上亿的数据表数据提取到mongdb,通过api单条插入,效率极低。通过第三方工具data-integration导入,效率还不够高。最终只能根据需求编写程序。
最初思路是解析oracle导出的dump二进制文件,在转换为bson二进制导入mongodb,但是根据测试,效率依旧较低。发现oracle与mongodb都采用批处理,效率算数有进步,最终决定采用编写程序实现。以下是在centos测试机器1万批量测得,鉴于代码未继续优化以及主机性能不强,后续效率还待测试:
在oracle导入mongodb时,通过oci批量提取数据,调用mongc driver批量写入mongddb,大幅提升效率,120万批量处理速度约21845条/s。代码还可继续优化,如使用oracle分页技术分多进程,理论提高页数倍,如有更好方式,也请分享,谢谢。以下为100万批量处理时速度记录:
oci程序中批量提取函数OCIDefineArrayOfStruct只能绑定静态数据,通过malloc开辟连续空间实现静态数组即可。以下为测试代码,后续请自行改进(需具备oci、mongodb、mongodb c driver、bson知识):
ToBson.h:
ToBson.cpp:
ToBson.json:
ToBson.json_bak:
最初思路是解析oracle导出的dump二进制文件,在转换为bson二进制导入mongodb,但是根据测试,效率依旧较低。发现oracle与mongodb都采用批处理,效率算数有进步,最终决定采用编写程序实现。以下是在centos测试机器1万批量测得,鉴于代码未继续优化以及主机性能不强,后续效率还待测试:
在oracle导入mongodb时,通过oci批量提取数据,调用mongc driver批量写入mongddb,大幅提升效率,120万批量处理速度约21845条/s。代码还可继续优化,如使用oracle分页技术分多进程,理论提高页数倍,如有更好方式,也请分享,谢谢。以下为100万批量处理时速度记录:
oci程序中批量提取函数OCIDefineArrayOfStruct只能绑定静态数据,通过malloc开辟连续空间实现静态数组即可。以下为测试代码,后续请自行改进(需具备oci、mongodb、mongodb c driver、bson知识):
ToBson.h:
/** * @file ToBson.h * @brief 导出ORACLE数据表或JSON文件为SBON文件、查看BSON文件工具 * @author wangcc3 * @date 2018-1-5 * @version 001 * @copyright Copyright (c) 2018,AsiaInfo(FzOcs) */ #ifndef _TO_BSON_H_ #define _TO_BSON_H_ #include <string> #include <oci.h> #include <bson.h> #include <bcon.h> #include <mongoc.h> namespace BM35 { using namespace std; // 地址对齐 #define ALIGNMENT 8 #define ADDRPADDING(p, a) (uintptr_t)(((uintptr_t)a - ((uintptr_t)p % (uintptr_t)a)) % (uintptr_t)a) #define ADDRALIGN(p, a) (char *)(((uintptr_t)p + ((uintptr_t)a - 1))&~((uintptr_t)a -1)) // 默认最大行数 #define _MAX_ROW_NUMS_ 1000000 /* typedef unsigned char ub1; typedef signed char sb1; typedef unsigned short ub2; typedef signed short sb2; typedef unsigned int ub4; typedef signed int sb4; typedef ub4 duword; typedef sb4 dsword; typedef dsword dword; */ // oracle句柄结构体 typedef struct _oci_env_ { OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIServer *srvhp; OCISession *usrhp; OCIStmt *smthp; OCIParam *paramhp; } OCI_ENV; // 字段信息 class OracleField { public: char *colName; char *colPoint; int colScale; int colOffset; ub2 colType; ub2 colDefineType; ub2 coLen; ub4 colNameLen; OCIDefine *ociDefine; }; // 配置结构体 class OCI_CONF { public: int flag; long rownum; long long begin; long long end; string table; string sql; string bfile; //可空 string jfile; string tns; string user; string passwd; string mongouri; string mongodb; string mongocollection; void init() { flag = 0; rownum = 0; begin = -1; end = -1; table = ""; sql = ""; bfile = ""; //可空 jfile = ""; passwd = ""; user = ""; tns = ""; mongouri = ""; mongodb = ""; mongocollection = ""; } }; class ToBson { public: ToBson(); ~ToBson(); // 运行入口 bool run(string & sJsonFile); // 运行入口 bool run(OCI_CONF & conf); // 获得错误信息 string getErrInfo(); private: // 运行 bool run(); // 输出容器配置信息 void printConf(vector<OCI_CONF>::iterator vIter); // 关闭BSON文件 void closeFile(); /* flag: 1ORACLETOBSON 2JSONTOBSON 3BSONTOJSON 4READBSON 5BSONNUMS 6ORACLETOMONGODB * 解析配置文件config.json: {"note":"遍历完所有flag=1 or 6的配置时,tns、user、passwd三个字段必须存在,字段实际生效按第一次出现配置"} {"note":"遍历完所有flag=6的配置时,uri、mdb二个字段必须存在,字段实际生效按第一次出现配置"} {"note":"flag: 1ORACLETOBSON 2JSONTOBSON 3BSONTOJSON 4READBSON 5BSONNUMS 6ORACLETOMONGODB"} {"flag":1,"tns":"SiC","user":"comm","passwd":"comm","table":"TEST9","bfile":"./TEST9.bson","sql":"","note":"bfile,[sql/table] can empty"} {"flag":1,"table":"TEST10","bfile":"./TEST10.bson"} {"flag":2,"bfile":"./test.bson","jfile":"./test.json","begin":0,"end":4,"note":"write 0-4 line json to bson file,default all"} {"flag":3,"bfile":"./test.bson","jfile":"./test.json","begin":0,"end":4,"note":"write 0-4 line bson to json file,default all"} {"flag":4,"bfile":"./TEST9.bson","begin":0,"end":4,"note":"read 0-4 line bson file info,default first 10 line"} {"flag":5,"bfile":"./TEST9.bson","note":"get bson file line nums"} {"flag":6,"table":"TEST9","uri":"mongodb://192.168.1.123:20000/","mdb":"mongodb","collection":"TEST9","note":"read oracle to mongodb"} */ bool ParseConfig(string sJsonFile); // 获得SQL表名 bool getTableName(char * sql, string &strOut, bool onlyTable = true); // 端口ORACLE连接 bool closeOracle(); // 端口MONGODB连接 bool closeMongodb(); // 将JSON文件写成BSON文件 bool writeBson(string sJsonFile, string sBsonFile, long lBegin = -1, long lEnd = -1); // 将BSON文件写成JSON文件 bool writeJson(string sBsonFile, string sJsonFile, long lBegin = -1, long lEnd = -1); // 初始化参数 bool initParameter(const string tableName = "", const string fileName = "", const long maxRowNum = _MAX_ROW_NUMS_); // 初始化MONGODB参数 bool initMongodb(const string database = "", const string table = ""); // 设置SQL语句 bool setSql(string sSql); // 连接ORACLE bool connectOracle(text *dnName,text *userName, text *passWord); // 连接MONGODB bool connectMongodb(const string &uri); // 打开MONGODB数据库 bool useDB(const string &databaseName); // 使用MONGODB数据表 bool useTable(const string &tableName); // 插入MONGODB bool insert(string & sJsonDoc); // 将表数据写成BSON文件 bool writeTableInfo(); // 写入BSON文件 bool writeBson(bson_t * bsonDoc, FILE *fp); // 检测ORACLE错误 bool checkErr(OCIError *pErr, sword lSattus); // 打开BSON文件 bool openFile(const char * sFileName); // 读取BSON文件信息 bool readBson(string sBsonFile, long lBegin = -1, long lEnd = -1); // 获得ORACLE定义类型 ub2 getDefineType(ub2 iType); // 获得缓存列偏移量 int getOffset(int col); // 获得BSON文件记录数 long getBsonNum(string sBsonFile); // 获得当前系统时间 string getTime(); // 去除换行 string trimNewline(char * str); private: bool bIsSetSql; bool isOracle; bool isMongodb; bool isWriteMongo; bool isInitDb; char sTnsName[32]; char sUserName[32]; char sPassWord[32]; char sTableName[32]; char sErr[512] = {0}; char sqlText[512]; char rowNum[32]; string sSqlTable; string sSqlRow; string sBsonFile; string errMsg; string nowTable; string mDatabaseName; string mTableName; string mUri; char *pBuf; char *pBufPoint; text *colName; FILE *fp; bson_t * docBson; mongoc_client_t *mClient; mongoc_database_t *mDatabase; mongoc_collection_t *mCollection; mongoc_bulk_operation_t *bulk; OCIDefine *dfnhp; OracleField *pOracleField; int iRowLen; ub2 coLen; ub4 colNum; ub4 colnameLen; ub4 rrows; ub4 psz; sb4 para_status; sb4 status; long lMaxRowNum; long lBufSize; long long lNowRow; long bsonNums; bson_t bsonDoc; bson_error_t bson_error; OCI_ENV stOciEnv; vector<OCI_CONF> vConf; vector<OCI_CONF>::iterator vIter; }; } #endif //_TO_BSON_H_
ToBson.cpp:
/** * @file ToBson.cpp * @brief 导出ORACLE数据表或JSON文件为SBON文件、查看BSON文件工具 * @author wangcc3 * @date 2018-1-5 * @version 001 * @copyright Copyright (c) 2018,AsiaInfo(FzOcs) */ #include <time.h> #include <iostream> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "ToBson.h" namespace BM35 { ToBson::ToBson() { fp = NULL; docBson = NULL; errMsg = "NO ERROR"; sSqlRow = ""; bIsSetSql = false; isInitDb = false; mDatabaseName = ""; mTableName = ""; mUri = ""; mCollection = NULL; mDatabase = NULL; mClient = NULL; bulk = NULL; pOracleField = NULL; pBuf = NULL; bson_init(&bsonDoc); memset(sTableName, 0, sizeof(sTableName)); memset(sqlText, 0, sizeof(sqlText)); memset(sTnsName, 0, sizeof(sTnsName)); memset(sUserName, 0, sizeof(sUserName)); memset(sPassWord, 0, sizeof(sPassWord)); } ToBson::~ToBson() { if(pOracleField) { for(int i = 0; i <colNum; i++) { if(pOracleField[i].colName) { delete [] pOracleField[i].colName; pOracleField[i].colName = NULL; } } delete[] pOracleField; pOracleField = NULL; } if(pBuf) { delete[] pBuf; pBuf = NULL; } closeFile(); bson_destroy(&bsonDoc); } bool ToBson::initMongodb(const string database, const string table) { if(database.empty() && mDatabaseName.empty()) { errMsg = "Mongodb database is empty"; return false; } if(!database.empty()) { if(!isInitDb) { useDB(database); } else if(database.compare(mDatabaseName)) { if(!useDB(database)) return false; } } else if(!useDB(mDatabaseName)) return false; if(!table.empty()) { useTable(table); } else if(!nowTable.empty()) { useTable(nowTable); } else { errMsg = "Mongodb table is empty"; return false; } return true; } bool ToBson::initParameter(const string tableName, const string fileName, const long maxRowNum) { nowTable = ""; if(!tableName.empty()) { strcpy(sTableName, tableName.c_str()); nowTable = sTableName; } else if(bIsSetSql) { if(!getTableName(sqlText, nowTable)) { errMsg = "Parsing sql failure when getting the table name"; return false; } } else { errMsg = "Parameter tableName and sql is empty"; return false; } if(!fileName.empty()) sBsonFile = fileName; else sBsonFile = "./" + nowTable + ".bson"; lMaxRowNum = maxRowNum; return true; } void ToBson::printConf(vector<OCI_CONF>::iterator vIter) { cout<<endl; cout<<"Config Info:"<<endl; cout<<"flag="<<vIter->flag<<endl; cout<<"table="<<vIter->table<<endl; cout<<"jfile="<<vIter->jfile<<endl; cout<<"bfile="<<vIter->bfile<<endl; cout<<"rownum="<<vIter->rownum<<endl; cout<<"sql="<<vIter->sql<<endl; cout<<"begin="<<vIter->begin<<endl; cout<<"end="<<vIter->end<<endl; cout<<endl; } string ToBson::trimNewline(char * str) { string _str = str; if(!_str.empty() ) { _str.erase(_str.find_last_not_of('\r') + 1); _str.erase(_str.find_last_not_of('\n') + 1); } return _str; } bool ToBson::run(OCI_CONF & conf) { vConf.clear(); if(conf.flag == 1 || conf.flag == 6) { if(conf.tns.empty() || conf.user.empty() || conf.passwd.empty()) { errMsg = "Parameter of tns or user or passed is empty"; return false; } strcpy(sTnsName, conf.tns.c_str()); strcpy(sUserName, conf.user.c_str()); strcpy(sPassWord, conf.passwd.c_str()); isOracle = true; if(conf.flag == 6) { if(conf.mongodb.empty() || conf.mongouri.empty()) { errMsg = "Parameter of muri or mdb is empty"; return false; } mDatabaseName = conf.mongodb; mTableName = conf.mongocollection; mUri = conf.mongouri; isMongodb = true; } else isMongodb = false; } else isOracle = false; vConf.push_back(conf); return run(); } bool ToBson::run(string & sJsonFile) { if(!ParseConfig(sJsonFile)) return false; return run(); } bool ToBson::run() { long count = 0; if(isOracle) { // check environment //export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK //Chinese: export NLS_LANG=AMERICAN_AMERICA.UTF8 if(getenv("NLS_LANG") == NULL) { errMsg = "Set env NLS_LANG first"; return false; } if(!connectOracle((text *)sTnsName, (text *)sUserName, (text *)sPassWord)) return false; if(isMongodb) if(!connectMongodb(mUri)) return false; } cout<<endl; for (vIter=vConf.begin(); vIter!=vConf.end(); vIter++) { if(vIter->flag == 1 || vIter->flag == 6) { if(!isOracle) { errMsg = "Can't connect oracle"; cout<<getErrInfo()<<endl; printConf(vIter); continue; } if((vIter->flag == 6) && !isMongodb) { errMsg = "Can't connect mongodb"; cout<<getErrInfo()<<endl; printConf(vIter); continue; } if(!vIter->sql.empty()) setSql(vIter->sql); if(!vIter->rownum) vIter->rownum = _MAX_ROW_NUMS_; if(!initParameter(vIter->table,vIter->bfile,vIter->rownum)) { cout<<getErrInfo()<<endl; printConf(vIter); continue; } if(vIter->flag == 6) { if(!initMongodb(vIter->mongodb, vIter->mongocollection)) { cout<<getErrInfo()<<endl; printConf(vIter); continue; } isWriteMongo = true; } else isWriteMongo = false; cout<<"Begin time:"<<getTime()<<endl; if(!writeTableInfo()) { cout<<getErrInfo()<<endl; printConf(vIter); continue; } cout<<"End time:"<<getTime()<<endl<<endl; } else if(vIter->flag == 2) { if(!writeBson(vIter->jfile, vIter->bfile, vIter->begin, vIter->end)) { cout<<getErrInfo()<<endl; printConf(vIter); continue; } } else if(vIter->flag == 3) { if(!writeJson(vIter->bfile, vIter->jfile, vIter->begin, vIter->end)) { cout<<getErrInfo()<<endl; printConf(vIter); continue; } } else if(vIter->flag == 4) { if(!readBson(vIter->bfile,vIter->begin,vIter->end)) { cout<<getErrInfo()<<endl; printConf(vIter); continue; } } else if(vIter->flag == 5) { cout<<"file "<<vIter->bfile<<" record nums="<<getBsonNum(vIter->bfile)<<endl<<endl; } count++; } cout<<endl<<"Total finish "<<count<<" config tasks"<<endl<<endl; if(isOracle) { if(!closeOracle()) return false; if(isMongodb) if(!closeMongodb()) return false; } return true; } bool ToBson::closeMongodb() { if(mCollection) mongoc_collection_destroy (mCollection); if(mDatabase) mongoc_database_destroy (mDatabase); if(mClient) mongoc_client_destroy (mClient); mongoc_cleanup (); return true; } string ToBson::getErrInfo() { return errMsg; } bool ToBson::getTableName(char * sql, string &strOut, bool onlyTable) { if(!sql || !strlen(sql)) { errMsg = "sql is empty"; return false; } string strSql= sql; string find_begin = "from"; size_t begin_postion; begin_postion = strSql.find(find_begin); if(onlyTable) { string find_end = "where"; size_t end_postion = strSql.find(find_end); if (end_postion != string::npos) strOut = strSql.substr(begin_postion+5, end_postion-begin_postion-6); else strOut = strSql.substr(begin_postion+5); } else { if (begin_postion != string::npos) strOut = strSql.substr(begin_postion+5); else return false; } return true; } string ToBson::getTime() { char year[5] = {0}; char month[3] = {0}; char day[3] = {0}; char hour[3] = {0}; char min[3] = {0}; char second[3] = {0}; char nowTime[20] = {0}; //string cNowTime = ""; time_t timep; struct tm *p; time(&timep); p = localtime(&timep); sprintf(year,"%d",1900 + p->tm_year); if(p->tm_mon < 10) sprintf(month, "0%d", 1 + p->tm_mon); else sprintf(month, "%d", 1 + p->tm_mon); if(p->tm_mday < 10) sprintf(day, "0%d", p->tm_mday); else sprintf(day, "%d", p->tm_mday); if(p->tm_hour < 10) sprintf(hour,"0%d",p->tm_hour); else sprintf(hour,"%d",p->tm_hour); if(p->tm_min < 10) sprintf(min, "0%d", p->tm_min); else sprintf(min, "%d", p->tm_min); if(p->tm_sec < 10) sprintf(second,"0%d",p->tm_sec); else sprintf(second,"%d",p->tm_sec); sprintf(nowTime, "%s/%s/%s %s:%s:%s",year, month, day, hour, min, second); //cNowTime = cNowTime + year + month + day + hour + min + second; return string(nowTime); } bool ToBson::connectMongodb(const string &uri) { if(uri.empty()) { errMsg = "Mongodb database connect uri is empty"; return false; } mongoc_init(); mClient = mongoc_client_new(uri.c_str()); if(!mClient) { errMsg = "Create mongodb client failed!\n"; return false; } return true; } bool ToBson::useDB(const string &databaseName) { if(databaseName.empty()) { errMsg = "databaseName is empty\n"; return false; } if(mCollection) { mongoc_collection_destroy(mCollection); mCollection = NULL; } if(mDatabase) { mongoc_database_destroy(mDatabase); mDatabase = NULL; } mDatabase = mongoc_client_get_database(mClient, databaseName.c_str()); if(!mDatabase) { errMsg = "Mongodb get database failed"; return false; } isInitDb = true; return true; } bool ToBson::insert(string & sJsonDoc) { docBson = bson_new_from_json ((const uint8_t*)sJsonDoc.c_str(), -1, &bson_error); if (!docBson) { errMsg = bson_error.message; return false; } if(!mongoc_collection_insert(mCollection, MONGOC_INSERT_NONE, docBson, NULL, &bson_error)) { errMsg = bson_error.message; return false; } bson_destroy (docBson); return true; } bool ToBson::useTable(const string &tableName) { if(tableName.empty()) { errMsg = "Mogndb tableName is empty\n"; return false; } if(mCollection) { mongoc_collection_destroy(mCollection); mCollection = NULL; } if(mDatabaseName.empty()) { errMsg = "Mongodb database is null, use useDB to init database instacne"; return false; } mCollection = mongoc_client_get_collection(mClient, mDatabaseName.c_str(), tableName.c_str()); if(!mCollection) { errMsg = "Mongodb get collection failed"; return false; } return true; } bool ToBson::connectOracle(text *dnName,text *userName, text *passWord) { OCIEnvCreate(&stOciEnv.envhp, OCI_DEFAULT, (dvoid *) 0, 0, 0, 0, (size_t) 0, (dvoid **) 0); OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **)&stOciEnv.errhp, OCI_HTYPE_ERROR, 0, (dvoid **) 0); OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **)&stOciEnv.srvhp, OCI_HTYPE_SERVER, 0, (dvoid **) 0); if(OCIServerAttach(stOciEnv.srvhp, stOciEnv.errhp, (text *) dnName, strlen((char *) dnName), OCI_DEFAULT) != OCI_SUCCESS) { errMsg = "Connection database failure"; return false; } OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **) &stOciEnv.svchp, OCI_HTYPE_SVCCTX, (size_t) 0, (dvoid **) 0); OCIAttrSet((dvoid *) stOciEnv.svchp, OCI_HTYPE_SVCCTX, (dvoid *) stOciEnv.srvhp, (ub4) 0, OCI_ATTR_SERVER, (OCIError *) stOciEnv.errhp); OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **) &stOciEnv.usrhp, OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0); OCIAttrSet((dvoid *) stOciEnv.usrhp, OCI_HTYPE_SESSION, (dvoid *) userName, (ub4) strlen((char *) userName), (ub4) OCI_ATTR_USERNAME, stOciEnv.errhp); OCIAttrSet((dvoid *) stOciEnv.usrhp, OCI_HTYPE_SESSION, (dvoid *) passWord, (ub4) strlen((char *) passWord), (ub4) OCI_ATTR_PASSWORD, stOciEnv.errhp); OCIAttrSet((dvoid *) stOciEnv.svchp, OCI_HTYPE_SVCCTX, (dvoid *) stOciEnv.usrhp, (ub4) 0, OCI_ATTR_SESSION, (OCIError *) stOciEnv.errhp); if(OCISessionBegin(stOciEnv.svchp, stOciEnv.errhp, stOciEnv.usrhp, OCI_CRED_RDBMS, OCI_DEFAULT) != OCI_SUCCESS) { errMsg = "Setting up user session failure"; return false; } if(!checkErr(stOciEnv.errhp, OCIHandleAlloc((dvoid *) stOciEnv.envhp, (dvoid **) &stOciEnv.smthp, OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0 ))) return false; return true; } bool ToBson::openFile(const char * sFileName) { if(!sFileName) { errMsg = "File is null"; return false; } if((fp=fopen(sFileName,"w+"))==NULL) { errMsg = "Fail to open file"; return false; } return true; } void ToBson::closeFile() { if(fp) { fclose(fp); fp = NULL; } } bool ToBson::ParseConfig(string sJsonFile) { if(sJsonFile.empty()) { errMsg = "Config file path is empty"; return false; } vConf.clear(); OCI_CONF tmpConf; tmpConf.init(); string key; uint32_t len=0; bson_json_reader_t *reader; bson_error_t error; bson_t doc = BSON_INITIALIZER; int b; bson_iter_t iter; char errInfo[256] = { 0 }; if (!(reader = bson_json_reader_new_from_file (sJsonFile.c_str(), &error))) { sprintf(errInfo, "Fail to open the json config file:%s", error.message); errMsg = errInfo; return false; } while ((b = bson_json_reader_read (reader, &doc, &error))) { if (b < 0) { //continue; sprintf(errInfo, "Parsing json file failure:%s", error.message); errMsg = errInfo; return false; } if (bson_iter_init(&iter, &doc)) { while(bson_iter_next(&iter)) { key = bson_iter_key(&iter); if(BSON_ITER_HOLDS_UTF8(&iter)) { if(!key.compare("tns")) { if(!strlen(sTnsName)) strcpy(sTnsName, bson_iter_utf8(&iter,&len)); } else if(!key.compare("user")) { if(!strlen(sUserName)) strcpy(sUserName, bson_iter_utf8(&iter,&len)); } else if(!key.compare("passwd")) { if(!strlen(sPassWord)) strcpy(sPassWord, bson_iter_utf8(&iter,&len)); } else if(!key.compare("table")) { tmpConf.table = bson_iter_utf8(&iter,&len); } else if(!key.compare("sql")) { tmpConf.sql = bson_iter_utf8(&iter,&len); } else if(!key.compare("bfile")) { tmpConf.bfile = bson_iter_utf8(&iter,&len); } else if(!key.compare("jfile")) { tmpConf.jfile = bson_iter_utf8(&iter,&len); } else if(!key.compare("uri")) { if(mUri.empty()) mUri = bson_iter_utf8(&iter,&len); } else if(!key.compare("mdb")) { tmpConf.mongodb = bson_iter_utf8(&iter,&len); if(mDatabaseName.empty()) mDatabaseName = tmpConf.mongodb; } else if(!key.compare("collection")) { tmpConf.mongocollection = bson_iter_utf8(&iter,&len); } else continue; } else if(BSON_ITER_HOLDS_INT64(&iter)) { if(!key.compare("flag")) { tmpConf.flag = bson_iter_int64(&iter); } else if(!key.compare("rownum")) { tmpConf.rownum = bson_iter_int64(&iter); } else if(!key.compare("begin")) { tmpConf.begin = bson_iter_int64(&iter); } else if(!key.compare("end")) { tmpConf.end = bson_iter_int64(&iter); } else continue; } else if(BSON_ITER_HOLDS_INT32(&iter)) { if(!key.compare("flag")) { tmpConf.flag = bson_iter_int32(&iter); } else if(!key.compare("rownum")) { tmpConf.rownum = bson_iter_int32(&iter); } else if(!key.compare("begin")) { tmpConf.begin = bson_iter_int32(&iter); } else if(!key.compare("end")) { tmpConf.end = bson_iter_int32(&iter); } else continue; } else { errMsg = "Conf file data type error"; } } if(tmpConf.flag == 1 || tmpConf.flag == 2 || tmpConf.flag == 3 || tmpConf.flag == 4 || tmpConf.flag == 5 || tmpConf.flag == 6) { vConf.push_back(tmpConf); tmpConf.init(); } } else { errMsg = "init bson iter error!"; return false; //continue; } bson_reinit (&doc); } bson_json_reader_destroy (reader); bson_destroy (&doc); if(vConf.empty()) { errMsg = "Conf vector are empty, initialization failed"; return false; } if(strlen(sTnsName) && strlen(sUserName) && strlen(sPassWord)) isOracle = true; else isOracle = false; if(mUri.empty() || mDatabaseName.empty()) isMongodb = false; else isMongodb = true; return true; } bool ToBson::writeJson(string sBsonFile, string sJsonFile, long lBegin, long lEnd) { if(sBsonFile.empty()) { errMsg = "The parameter sBsonFile is empty"; return false; } if(sJsonFile.empty()) { errMsg = "The parameter sJsonFile is empty"; return false; } FILE *jsonfp; char errInfo[256] = { 0 }; bson_reader_t *reader; const bson_t *b; bson_error_t error; long lCount = 0; if(!(reader = bson_reader_new_from_file(sBsonFile.c_str(), &error))) { sprintf(errInfo, "Fail to open the bson file:%s", error.message); errMsg = errInfo; return false; } if((jsonfp=fopen(sJsonFile.c_str(),"w+"))==NULL) { errMsg = "Fail to open the bson file"; return false; } while((b = bson_reader_read (reader, NULL))) { if(lEnd >= 0) { if(lCount >= lEnd) break; } if(lBegin > lCount) { lCount ++; continue; } fprintf(jsonfp, "%s\n", bson_as_json (b, NULL)); lCount ++; } fclose(jsonfp); bson_reader_destroy (reader); return true; } bool ToBson::writeBson(string sJsonFile, string sBsonFile, long lBegin,long lEnd) { //参数 /ccw/test.json /ccw/test.bson if(sJsonFile.empty() || sBsonFile.empty()) { errMsg = "Parameter jsonfile or bsonfile is empty"; return false; } FILE *bsonfp; bson_json_reader_t *reader; bson_error_t error; bson_t doc = BSON_INITIALIZER; int b; char errInfo[256] = { 0 }; long lCount = 0; if((bsonfp=fopen(sBsonFile.c_str(),"w+"))==NULL) { errMsg = "Fail to open the bson file"; return false; } if (!(reader = bson_json_reader_new_from_file (sJsonFile.c_str(), &error))) { sprintf(errInfo, "Fail to open the json file:%s", error.message); errMsg = errInfo; return false; } while ((b = bson_json_reader_read (reader, &doc, &error))) { if (b < 0) { sprintf(errInfo, "Parsing json file failure:%s", error.message); errMsg = errInfo; return false; } if(lEnd >= 0) { if(lCount >= lEnd) break; } if(lBegin > lCount) { lCount ++; continue; } if (fwrite (bson_get_data(&doc), 1, doc.len, bsonfp) != doc.len) { errMsg = "Write file failure"; return false; } lCount ++; bson_reinit (&doc); } bson_json_reader_destroy (reader); bson_destroy (&doc); fclose(bsonfp); return true; } bool ToBson::writeBson(bson_t * bsonDoc, FILE *fp) { if(!fp) { errMsg = "File pointers are not initialized"; return false; } if (fwrite(bson_get_data(bsonDoc), 1, bsonDoc->len, fp) != bsonDoc->len) { errMsg = "Invocation of fwrite() error, write file failure"; return false; } return true; } long ToBson::getBsonNum(string sBsonFile) { if(sBsonFile.empty()) { errMsg = "Parameter sBsonFile is empty"; return -1; } char errInfo[256] = { 0 }; bson_reader_t *reader; bson_error_t error; long lCount = 0; if(!(reader = bson_reader_new_from_file(sBsonFile.c_str(), &error))) { sprintf(errInfo, "Fail to open the bson file:%s", error.message); errMsg = errInfo; return -1; } while(bson_reader_read (reader, NULL)) { lCount ++; } bson_reader_destroy (reader); return lCount; } bool ToBson::readBson(string sBsonFile,long lBegin,long lEnd) { if(sBsonFile.empty()) { errMsg = "The parameter sBsonFile is empty"; return false; } char errInfo[256] = { 0 }; bson_reader_t *reader; const bson_t *b; bson_error_t error; char *str; long lCount = 0; if(!(reader = bson_reader_new_from_file(sBsonFile.c_str(), &error))) { sprintf(errInfo, "Fail to open the bson file:%s", error.message); errMsg = errInfo; return false; } while((b = bson_reader_read (reader, NULL))) { if((lBegin < 0) && (lEnd < 0)) { if(lCount >= 10) break; } if(lEnd >= 0) { if(lCount >= lEnd) break; } if(lBegin > lCount) { lCount ++; continue; } str = bson_as_json (b, NULL); cout<<str<<endl; bson_free (str); lCount ++; } bson_reader_destroy (reader); return true; } bool ToBson::setSql(string sSql) { bIsSetSql = false; if(sSql.empty()) { errMsg = "sql is empty in setSql()"; return false; } sprintf(sqlText, "%s" , sSql.c_str()); bIsSetSql = true; return true; } ub2 ToBson::getDefineType(ub2 iType) { ub2 type; switch(iType) { case SQLT_AFC: case SQLT_VCS: case SQLT_CHR: case SQLT_UIN: case SQLT_INT: case SQLT_FLT: case SQLT_NUM: case SQLT_RDD: type = SQLT_STR; break; case SQLT_DAT: type = SQLT_ODT; break; // case SQLT_FLT: // case SQLT_NUM: // type = SQLT_VNU; // break; default: type = iType; break; } return type; } int ToBson::getOffset(int col) { if(col <= 0 ) return 0; int offset = 0; int i = 0; for(i = col -1; i >= 0; i--) { offset += (pOracleField[i].coLen + ALIGNMENT -1 + 1); } return offset; } bool ToBson::writeTableInfo() { if(!bIsSetSql && !strlen(sTableName)) { errMsg = "TableName or sql statement is not set!"; return false; } if(!bIsSetSql) { sSqlRow.clear(); sprintf(sqlText, "select * from %s" ,sTableName); sSqlRow = sSqlRow + "select count(*) from " + sTableName; } else { if(!getTableName(sqlText, sSqlTable, false)) { errMsg = "Parsing sql failure when getting the table name"; return false; } sSqlRow = "select count(*) from " + sSqlTable; } if(!checkErr(stOciEnv.errhp, OCIStmtPrepare(stOciEnv.smthp, stOciEnv.errhp, (text *)sSqlRow.c_str(), (ub4)sSqlRow.length(), OCI_NTV_SYNTAX, OCI_DEFAULT))) return false; if(!checkErr(stOciEnv.errhp, OCIStmtExecute(stOciEnv.svchp, stOciEnv.smthp, stOciEnv.errhp, 0, 0, NULL, NULL, OCI_DEFAULT))) return false; para_status = OCIDefineByPos(stOciEnv.smthp, &dfnhp, stOciEnv.errhp, 1, (dvoid*)rowNum, sizeof(rowNum) + 1, SQLT_STR, 0, 0, 0, OCI_DEFAULT); if (para_status != OCI_SUCCESS) { checkErr(stOciEnv.errhp,para_status); return false; } para_status = OCIStmtFetch(stOciEnv.smthp, stOciEnv.errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); if (para_status == OCI_NO_DATA) { errMsg = "Get rowNum error"; return false; } cout<<"["<<nowTable<<"]Total row nums="<<rowNum<<endl; lNowRow = atol(rowNum); if(!lNowRow) return true; if(lNowRow < lMaxRowNum) lMaxRowNum = lNowRow; if(!checkErr(stOciEnv.errhp, OCIStmtPrepare(stOciEnv.smthp, stOciEnv.errhp, (text *)sqlText, (ub4)strlen((const char *) sqlText), OCI_NTV_SYNTAX, OCI_DEFAULT))) return false; if(!checkErr(stOciEnv.errhp, OCIStmtExecute(stOciEnv.svchp, stOciEnv.smthp, stOciEnv.errhp, 0, 0, NULL, NULL, OCI_DEFAULT))) return false; OCIAttrGet((dvoid*)stOciEnv.smthp, OCI_HTYPE_STMT, (dvoid*)&colNum, (ub4 *)0, OCI_ATTR_PARAM_COUNT, stOciEnv.errhp); pOracleField = new OracleField[colNum]; if(!pOracleField) { errMsg = "Allocation field list memory failure"; return false; } int i = 0; iRowLen = 0; for (i=0; i< colNum; i++) { para_status = OCIParamGet(stOciEnv.smthp, OCI_HTYPE_STMT, stOciEnv.errhp, (void **) &stOciEnv.paramhp, (ub4)i+1); OCIAttrGet((dvoid*)stOciEnv.paramhp, OCI_DTYPE_PARAM, (dvoid**)&colName, &pOracleField[i].colNameLen, OCI_ATTR_NAME, stOciEnv.errhp); pOracleField[i].colName = new char[pOracleField->colNameLen+1]; if(!pOracleField[i].colName) { errMsg = "Allocation field name memory failure"; return false; } strncpy(pOracleField[i].colName, (char*)colName, pOracleField[i].colNameLen); pOracleField[i].colName[pOracleField[i].colNameLen] = '\0'; OCIAttrGet((dvoid*)stOciEnv.paramhp, OCI_DTYPE_PARAM, (dvoid *)&pOracleField[i].colScale, 0, OCI_ATTR_SCALE, stOciEnv.errhp); OCIAttrGet((dvoid*)stOciEnv.paramhp, OCI_DTYPE_PARAM, (dvoid*)&pOracleField[i].colType, 0, OCI_ATTR_DATA_TYPE, stOciEnv.errhp); OCIAttrGet((dvoid*)stOciEnv.paramhp, OCI_DTYPE_PARAM, (dvoid*)&pOracleField[i].coLen, 0, OCI_ATTR_DATA_SIZE, stOciEnv.errhp); if(pOracleField[i].colType == SQLT_LNG || pOracleField[i].colType == SQLT_LBI || pOracleField[i].colType == SQLT_LVC || pOracleField[i].colType == SQLT_LVB || pOracleField[i].colType == SQLT_CLOB || pOracleField[i].colType == SQLT_BLOB) { errMsg = "Type unsupport"; return false; } pOracleField[i].colDefineType = getDefineType(pOracleField[i].colType); pOracleField[i].colOffset = getOffset(i); iRowLen = iRowLen + pOracleField[i].coLen + (ALIGNMENT -1) + 1; } iRowLen = iRowLen + ((ALIGNMENT - (iRowLen % ALIGNMENT)) % ALIGNMENT); lBufSize = iRowLen * lMaxRowNum; pBuf = new char[lBufSize]; if(pBuf == NULL) { errMsg = "Allocation buf memory failure"; return false; } memset(pBuf, 0, lBufSize); for(i=0; i< colNum; i++) { pBufPoint = pBuf + pOracleField[i].colOffset; pOracleField[i].colPoint = ADDRALIGN(pBufPoint,ALIGNMENT); para_status = OCIDefineByPos(stOciEnv.smthp, &pOracleField[i].ociDefine, stOciEnv.errhp, i+1, (dvoid*)pOracleField[i].colPoint, (sb4)(pOracleField[i].coLen + 1), pOracleField[i].colDefineType, 0, 0, 0, OCI_DEFAULT); if(!checkErr(stOciEnv.errhp, para_status)) return false; para_status=OCIDefineArrayOfStruct(pOracleField[i].ociDefine, stOciEnv.errhp, (ub4)iRowLen, 0, (ub4)0, 0); if(!checkErr(stOciEnv.errhp, para_status)) return false; } if(!isWriteMongo) { if(!openFile(sBsonFile.c_str())) return false; } lNowRow = 0; char tmpStr[32] = {0}; ub4 buf_size = 32; psz = sizeof(ub4); long j = 0; while(true) { status = OCIStmtFetch(stOciEnv.smthp, stOciEnv.errhp, lMaxRowNum, OCI_FETCH_NEXT, OCI_DEFAULT); if(!checkErr(stOciEnv.errhp, OCIAttrGet((dvoid *)stOciEnv.smthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&rrows, (ub4 *)&psz, (ub4)OCI_ATTR_ROWS_FETCHED, stOciEnv.errhp))) { errMsg = "Rows fetched of OCIAttrGet() failed"; return false; } if(!rrows) break; if(isWriteMongo) { bulk = mongoc_collection_create_bulk_operation(mCollection, true, NULL); if(!bulk) { errMsg = "Create bulk failed"; return false; } } for(j = 0; j < rrows; j++) { bson_reinit(&bsonDoc); for(i = 0; i < colNum; i++) { pBufPoint = pOracleField[i].colPoint + j*iRowLen; //printf("value=%x\n",pBufPoint); switch(pOracleField[i].colType) { case SQLT_AFC: case SQLT_VCS: case SQLT_CHR: case SQLT_RDD: BSON_APPEND_UTF8(&bsonDoc, pOracleField[i].colName, pBufPoint); break; case SQLT_DAT: para_status = OCIDateToText(stOciEnv.errhp, (OCIDate*)pBufPoint, (oratext*)"yyyymmddhh24miss", strlen("yyyymmddhh24miss"), (oratext*)"American", strlen("American"), &buf_size, (oratext*)tmpStr); if(!checkErr(stOciEnv.errhp, para_status)) cout<<"Use Func OCIDateToText() failed"<<endl; if(strcmp(tmpStr, "00000000000000")) BSON_APPEND_UTF8(&bsonDoc, pOracleField[i].colName, tmpStr); tmpStr[0] = '\0'; break; case SQLT_FLT: case SQLT_NUM: if(strlen(pBufPoint)) { if(pOracleField[i].colScale != 0) BSON_APPEND_DOUBLE(&bsonDoc, pOracleField[i].colName, atof(pBufPoint)); else BSON_APPEND_INT64(&bsonDoc, pOracleField[i].colName, atoll(pBufPoint)); } break; case SQLT_UIN: case SQLT_INT: if(strlen(pBufPoint)) BSON_APPEND_INT64(&bsonDoc, pOracleField[i].colName, atoll(pBufPoint)); break; case SQLT_BLOB: case SQLT_BIN: cout<<"type nosupper"<<endl; errMsg = "type nosupper"; break; default: cout<<"other type nosupper"<<endl; errMsg = "other type nosupper"; break; } pBufPoint[0] = '\0'; } if(isWriteMongo) { mongoc_bulk_operation_insert(bulk, &bsonDoc); } else { if(!writeBson(&bsonDoc,fp)) return false; } } if(isWriteMongo) { if (!mongoc_bulk_operation_execute(bulk, NULL, &bson_error)) { errMsg = bson_error.message; mongoc_bulk_operation_destroy(bulk); return false; } mongoc_bulk_operation_destroy(bulk); } lNowRow = lNowRow + rrows; // When rrows is less than lMaxRowNum, also return OCI_NO_DATA if(status == OCI_NO_DATA) break; } closeFile(); if(pOracleField) { for(int i = 0; i <colNum; i++) { if(pOracleField[i].colName) { delete [] pOracleField[i].colName; pOracleField[i].colName = NULL; } } delete[] pOracleField; pOracleField = NULL; } if(pBuf) { delete[] pBuf; pBuf = NULL; } cout <<"["<<nowTable<<"]Rows has been processed="<<lNowRow<<endl; return true; } bool ToBson::checkErr(OCIError *pErr, sword lSattus) { sb4 iErrCode = 0; switch (lSattus) { case OCI_SUCCESS: strcpy(sErr, "OCI_SUCCESS"); break; case OCI_SUCCESS_WITH_INFO: strcpy(sErr, "OCI_SUCCESS_WITH_INFO"); break; case OCI_NO_DATA: strcpy(sErr, "OCI_NO_DATA"); break; case OCI_ERROR: OCIErrorGet((dvoid *) pErr, (ub4) 1, (text *) NULL, &iErrCode, (text *) sErr, (ub4) sizeof(sErr), (ub4) OCI_HTYPE_ERROR); break; case OCI_NEED_DATA: strcpy(sErr, "OCI_NEED_DATA"); break; case OCI_INVALID_HANDLE: strcpy(sErr, "OCI_INVALID_HANDLE"); break; case OCI_STILL_EXECUTING: strcpy(sErr, "OCI_STILL_EXECUTING"); break; case OCI_CONTINUE: strcpy(sErr, "OCI_CONTINUE"); break; default: break; } if(OCI_SUCCESS != lSattus && OCI_SUCCESS_WITH_INFO != lSattus) { errMsg = sErr; return false; } return true; } bool ToBson::closeOracle() { if(stOciEnv.smthp) { if(!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.smthp, OCI_HTYPE_STMT))) return false; stOciEnv.smthp = NULL; } if(stOciEnv.svchp && stOciEnv.errhp && stOciEnv.usrhp) { if(!checkErr(stOciEnv.errhp,OCISessionEnd(stOciEnv.svchp, stOciEnv.errhp, stOciEnv.usrhp, OCI_DEFAULT))) return false; } if (stOciEnv.usrhp) { if(!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.usrhp, OCI_HTYPE_SESSION))) return false; stOciEnv.usrhp = NULL; } if (stOciEnv.srvhp && stOciEnv.errhp) { if (!checkErr(stOciEnv.errhp, OCIServerDetach(stOciEnv.srvhp, stOciEnv.errhp, OCI_DEFAULT))) return false; } if (stOciEnv.srvhp) { if (!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.srvhp, OCI_HTYPE_SERVER))) return false; stOciEnv.srvhp = NULL; } if(stOciEnv.svchp) { if (!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.svchp, OCI_HTYPE_SVCCTX))) return false; stOciEnv.svchp = NULL; } if (stOciEnv.errhp) { if (!checkErr(stOciEnv.errhp, OCIHandleFree(stOciEnv.errhp, OCI_HTYPE_ERROR))) return false; stOciEnv.errhp = NULL; } if (stOciEnv.envhp) { if (!checkErr(stOciEnv.errhp,OCIHandleFree(stOciEnv.envhp, OCI_HTYPE_ENV))) return false; stOciEnv.envhp = NULL; } return true; } } using namespace std; using namespace BM35; int main(int argc, char *argv[]) { string confFile; string strYN; string rowNum; string bFile; string jFile; string table; string end; string start; string sql; string tns; string user; string passwd; string mDb; string mUri; string mCollection; OCI_CONF conf; conf.init(); for (int c; (c = getopt(argc, argv, "f:hHr:b:j:t:e:s:q:p:u:n:d:c:i:")) != EOF;) { switch (c) { case 'f': confFile = optarg; break; case 'r': rowNum = optarg; break; case 'i': mUri = optarg; break; case 'd': mDb = optarg; break; case 'c': mCollection = optarg; break; case 'p': passwd = optarg; break; case 'u': user = optarg; break; case 'n': tns = optarg; break; case 'b': bFile = optarg; break; case 'j': jFile = optarg; break; case 'q': sql = optarg; break; case 't': table = optarg; break; case 'e': end = optarg; break; case 's': start = optarg; break; case '?': case 'h': case 'H': cout<<"Usage: ToBson \n"; cout<<" -f confFile [default ./ToBson.json]\n"; cout<<" or 1,2,3,4,5 6[1ORACLETOBSON 2JSONTOBSON 3BSONTOJSON 4READBSON 5BSONNUMS 6ORACLETOMONGODB]\n"; cout<<" -r rownum \n"; cout<<" -p passwd \n"; cout<<" -u user \n"; cout<<" -n tns \n"; cout<<" -b bfile \n"; cout<<" -j jfile \n"; cout<<" -q sql \n"; cout<<" -s start \n"; cout<<" -e end \n"; cout<<" -t table \n"; cout<<" -i uri \n"; cout<<" -d mongoDb \n"; cout<<" -c collection \n"; cout<<" -h printf help\n"; cout<<" example:ToBson -f ./ToBson.json \n"; cout<<" ToBson -f 4 -b ./test9.bson\n"; cout<<" ToBson -f 1 -u comm -p comm -n SiC -t test9\n"; cout<<" ToBson -f 6 -u comm -p comm -n SiC -t test9 -d mongodb -i mongodb://192.168.1.123:20000/\n"; cout<<" more detail reference file ToBson.json \n"; exit(-1); break; default: break; } } ToBson toBson; if(confFile.empty()) { cout<<"Using ./ToBson.json file to run(y/n):"<<endl; cin>>strYN; if(!strYN.compare("Y") || !strYN.compare("y")) confFile = "./ToBson.json"; else return 0; } else if(!confFile.compare("1") || !confFile.compare("2") || !confFile.compare("3") || !confFile.compare("4") || !confFile.compare("5") || !confFile.compare("6")) { conf.flag = atoi(confFile.c_str()); if(!rowNum.empty()) conf.rownum = atol(rowNum.c_str()); if(!end.empty()) conf.end = atoll(end.c_str()); if(!start.empty()) conf.begin = atoll(start.c_str()); conf.bfile = bFile; conf.jfile = jFile; conf.table = table; conf.sql = sql; conf.tns = tns; conf.user = user; conf.passwd = passwd; conf.mongouri = mUri; conf.mongocollection = mCollection; conf.mongodb = mDb; if(!toBson.run(conf)){ cout<<toBson.getErrInfo()<<endl; return -1; } return 0; } if(!toBson.run(confFile)){ cout<<toBson.getErrInfo()<<endl; return -1; } return 0; }
ToBson.json:
{"note":"遍历完所有flag=1 or 6的配置时,tns、user、passwd三个字段必须存在,字段实际生效按第一次出现配置"} {"note":"遍历完所有flag=6的配置时,uri、mdb二个字段必须存在,字段实际生效按第一次出现配置"} {"note":"flag: 1ORACLETOBSON 2JSONTOBSON 3BSONTOJSON 4READBSON 5BSONNUMS 6ORACLETOMONGODB"} {"flag":1,"tns":"SiC","user":"comm","passwd":"comm","table":"TEST9","bfile":"./TEST9.bson","sql":"","note":"bfile,[sql/table] can empty"} {"flag":1,"table":"TEST10","bfile":"./TEST10.bson"} {"flag":2,"bfile":"./test.bson","jfile":"./test.json","begin":0,"end":4,"note":"write 0-4 line json to bson file,default all"} {"flag":3,"bfile":"./test.bson","jfile":"./test.json","begin":0,"end":4,"note":"write 0-4 line bson to json file,default all"} {"flag":4,"bfile":"./TEST9.bson","begin":0,"end":4,"note":"read 0-4 line bson file info,default first 10 line"} {"flag":5,"bfile":"./TEST9.bson","note":"get bson file line nums"} {"flag":6,"table":"TEST9","uri":"mongodb://192.168.1.123:20000/","mdb":"mongodb","collection":"TEST9","note":"read oracle to mongodb"}
ToBson.json_bak:
{"flag":6,"tns":"SiC","user":"comm","passwd":"comm","table":"TEST","uri":"mongodb://192.168.1.127:27017/","mdb":"mongodb","rownum":1200000}
相关文章推荐
- Python连接mongodb提取部分字段内数据并写入txt文件
- oracle查询数据,以asci写入文件
- C# 在Oracle中写入CLOB数据
- Java对Oracle中Clob类型数据的读取和写入
- JDBC+Hibernate将Blob数据写入Oracle
- kettle-6.0从MySQL中读取数据并写入MongoDB的教程
- JDBC+Hibernate将Blob数据写入Oracle
- kettle 从hive中读取数据并写入MongoDB
- [置顶] python 生成内嵌式字典(dict)-案例从python提取内嵌json写入mongodb
- mysql没有oracle 那样一次性把data buffer 数据写入磁盘
- 网站用户行为数据统计与分析之二:数据写入mongodb
- Java对Oracle中Clob类型数据的读取和写入
- 将oracle中blob数据写入文件,再把文件读取插入数据库
- Oracle、PostgreSQL与Mysql数据写入性能对比
- Oracle 学习:PL/SQL循序渐进全面学习教程--课程三 从多个表中提取数据
- 使用JDBC和Hibernate来写入Blob型数据到Oracle中
- 用JDBC和Hibernate来写入Blob型数据到Oracle中
- 向oracle写入大数据
- 如何将Oracle导出的数据导入MongoDB
- Java将数据写入Oracle的Clob字段中