今日趁空,嘗試用C++操作Oracle數據庫。大致步驟列舉如下:
1.安裝OCCI
如果oracle數據庫默認沒有安裝OCCI,可以自己從官網上下載與自己數據庫版本一致的API,地址:http://www.oracle.com/technetwork/topics/linuxsoft-082809.html ; 其中包含四個軟件包:
oracle-instantclient-sqlplus-10.2.0.5-1.i386.rpm oracle-instantclient-devel-10.2.0.5-1.i386.rpm oracle-instantclient-odbc-10.2.0.5-1.i386.rpm oracle-instantclient-basic-10.2.0.5-1.i386.rpm
安裝完成之后,會在/usr/lib下多個oracle 共享庫文件夾,在/usr/include下多個oracle 頭文件(接口)文件夾(可以將他們放到環境變量中)。我的數據庫版本是10.2.0,下面以此為例。
2.編寫HelloWorld程序測試連接
#include <iostream> #define LINUXOCCI //避免函數重定義錯誤 #include <occi.h> using namespace std; using namespace oracle::occi; int main() { Environment *env=Environment::createEnvironment(Environment::DEFAULT); cout<<"success"<<endl; string name = "scott"; string pass = "tiger"; string srvName = "127.0.0.1:1522/orcl"; try { Connection *conn = env->createConnection(name, pass); cout<<"conn success"<<endl; env->terminateConnection(conn); } catch(SQLException e) { cout<<e.what()<<endl; return -1; } Environment::terminateEnvironment(env); cout<<"end!"<<endl; return 0;
}
編譯命令:
g++ test.cc -o test -I/usr/include/oracle/10.2.0.5/client -L/usr/lib/oracle/10.2.0.5/client/lib -locci -lsqlplus
我沒有將occi的路徑加入到環境變量中,所以此處要顯示列出目錄才能通過編譯,找到共享庫。
運行./test會報錯,libocci.so找不到,解決辦法很簡單:將/usr/lib/oracle/.../lib下的庫加入到LD_LIBRARY_PATH中就可以了。
輸出結果:
success conn success end!
注:這件不幸的事情可能只發生在我身上了,本人系統中有三個用戶,其中一個是oracle,而程序是用另一個用戶寫的,於是編譯通過了,但是運行總是報錯:
ORA-12162: TNS:net service name is incorrectly specified
后來查明,這個是由於沒有設置並導出ORACLE_SID。換了oracle用戶試試,居然運行通過了,真的很傷心,原來那個用戶沒有設置Oracle環境變臉怎么能直接本地訪問呢。
3.進行一些操作,執行sql語句
Employees.h
/* * A simple OCCI test application * This file contains the Employees class declaration */ #include <iostream> #include <occi.h> #include <iomanip> using namespace oracle::occi; using namespace std; class Employees { public: Employees(); virtual ~Employees(); void List(); private: Environment *env; Connection *con; string user; string passwd; string db; }; Employees::Employees() { /* 69 * connect to the test database as the HR 70 * sample user and use the EZCONNECT method 71 * of specifying the connect string. Be sure 72 * to adjust for your environment! The format 73 * of the string is host:port/service_name 74 */ user = "scott"; passwd = "tiger"; db = "127.0.0.1:1522/orcl"; env = Environment::createEnvironment(Environment::DEFAULT); try { con = env->createConnection(user, passwd, db); } catch (SQLException& ex) { cout << ex.getMessage(); exit(EXIT_FAILURE); } } Employees::~Employees() { env->terminateConnection (con); Environment::terminateEnvironment (env); } void Employees::List() { /* 104 * simple test method to select data from 105 * the employees table and display the results 106 */ Statement *stmt = NULL; ResultSet *rs = NULL; string sql = "select EMPNO, ENAME, JOB " \ "from EMP order by EMPNO"; try { stmt = con->createStatement(sql); } catch (SQLException& ex) { cout << ex.getMessage(); } if (stmt) { try { stmt->setPrefetchRowCount(32); rs = stmt->executeQuery(); } catch (SQLException& ex) { cout << ex.getMessage(); } if (rs) { cout << endl << setw(8) << left << "EMPNO" << setw(22) << left << "ENAME" << setw(27) << left << "JOB" << endl; cout << setw(8) << left << "======" << setw(22) << left << "====================" << setw(27) << left << "=========================" << endl; while (rs->next()) { cout << setw(8) << left << rs->getInt(1) << setw(22) << left << (rs->isNull(2) ? "n/a" : rs->getString(2)) << setw(27) << left << rs->getString(3) << endl; } cout << endl; stmt->closeResultSet(rs); } con->terminateStatement(stmt); } }
main.cc
#include "Employees.h" using namespace std; using namespace oracle::occi; int main (void) { /* 48 * create an instance of the Employees class, 49 * invoke the List member, delete the instance, 50 * and prompt to continue... 51 */ Employees *pEmployees = new Employees(); pEmployees->List(); delete pEmployees; cout << "ENTER to continue..."; cin.get(); return 0; }
運行結果就不說了,反正是oracle里自帶的emp表。