專案原定 Linux 部署,臨時切換 Windows 平台。OCCI 11 與 VC9 相容性不佳,Environment 初始化即報錯,經長時間嘗試無果,決定放棄 OCCI,改用底層 OCI 並自行封裝輕量級 C++ 包裝器 ocipp(Oracle C++ Interface Parallel/Simple)。
同時開啟 SQL*Plus 與 ocipp 程式測試 DML(UPDATE/DELETE)時,程式卡在 execute 呼叫。根因:SQL*Plus 預設手動提交,而 ocipp 採 OCI_COMMIT_ON_SUCCESS 自動提交,兩者鎖衝突。教訓:調試 OCI 介面時,切勿同時開啟另一資料庫會話進行未提交的寫入操作。
三大核心類別:
Environment:管理 OCI 環境句柄與錯誤句柄,單例模式Connection:封裝伺服器連線、服務上下文、會話認證Statement:支援字串綁定/定義、執行、逐行抓取僅支援 std::string 類型的定義與綁定,適合純文字資料場景,代碼精簡、風險自負。
Environment::Environment(unsigned int mode) : _env(NULL), _err(NULL) {
makeEnvironment(mode);
}
void Environment::makeEnvironment(unsigned int mode) {
int ret = OCIEnvCreate(&_env, mode, NULL, NULL, NULL, NULL, 0, NULL);
if (ret != OCI_SUCCESS || _env == NULL)
throw Exception(ret, "create Environment failed.");
ret = OCIHandleAlloc((const void*)_env, (void**)&_err, OCI_HTYPE_ERROR, 0, NULL);
if (ret != OCI_SUCCESS || _err == NULL)
throw Exception(ret, _err, "create Error failed.");
}
Connection* Environment::makeConnection(const string& user, const string& passwd, const string& server) {
Connection *conn = new Connection(this);
// 1. 分配 Server Handle
// 2. 分配 Service Context Handle
// 3. OCIServerAttach 連接伺服器
// 4. 設定 SVCCTX 的 OCI_ATTR_SERVER
// 5. 分配 Session Handle、設定 Username/Password
// 6. OCISessionBegin 開啟會話
// 7. 設定 SVCCTX 的 OCI_ATTR_SESSION
return conn;
}
int Statement::bindString(unsigned int pos, const string& val) {
OCIBind* bd = NULL;
int ret = OCIBindByPos(_stmt, &bd, _conn->getEnvironment()->getError(), pos,
(void*)val.c_str(), val.size() + 1, SQLT_STR,
NULL, NULL, NULL, 0, NULL, OCI_DEFAULT);
if (ret != OCI_SUCCESS) throw Exception(ret, ..., "bind String failed.");
return 0;
}
int Statement::execute() {
unsigned short type;
OCIAttrGet(_stmt, OCI_HTYPE_STMT, &type, 0, OCI_ATTR_STMT_TYPE, _conn->getEnvironment()->getError());
int ret = OCIStmtExecute(_conn->getSvc(), _stmt, _conn->getEnvironment()->getError(),
(type != OCI_STMT_SELECT ? 1 : 0), 0, NULL, NULL, OCI_COMMIT_ON_SUCCESS);
if (ret != OCI_SUCCESS) throw Exception(ret, ..., "execute Stmt failed.");
return 0;
}
ocipp 雖非生產級庫,但展示了 OCI 核心流程:環境→連線→陳述式→綁定/定義→執行→抓取→清理。若需健壯方案,建議直接使用 OCCI(新版已修復 VC 相容性)或成熟第三方庫如 OTL、SOCI。