1. 程式人生 > 其它 >在 debian 上使用 qt 訪問 oracle 資料庫

在 debian 上使用 qt 訪問 oracle 資料庫

技術標籤:SQLServer/mySQL/Oracle資料庫技術

原文地址::https://ouonline.net/connecting-to-oracle-with-qt-on-debian

之前的一個使用 oracle 的專案自從我把資料庫裝好之後就沒有下文了,最近迎來了另一個也需要使用 oracle 的專案。由於 oracle 不是開源的,為了能在 Linux 下使用 qt 訪問,只好自己編譯對應的驅動。在網上找了一堆資料,又折騰了好幾天,終於在今天晚上成功了,在這裡記錄一下。

先說一下環境:debian 6.0,qt sdk 4.8.1,oracle 11gR2。本文主要記錄的是怎樣編譯驅動和怎樣連線,關於 oracle 資料庫伺服器端安裝中的一些問題可以參考之前的一篇

筆記

準備工作

下載 qt sdk。因為編譯的時候 qt 工具鏈和原始碼要保持一致,而 debian 6 源裡的 qt 版本是 4.6.3,官網上已經找不到對應的原始碼包了,所以下載 sdk 安裝(sdk 包含工具鏈和對應版本的原始碼),安裝的時候要注意把安裝 source code 的選項勾上。這裡使用 QTDIR 表示 qt sdk 的安裝目錄(這個環境變數不是必須的,只是為了描述方便,因此在下面出現這個目錄的時候把它替換成實際的安裝目錄)。

安裝和 oracle 服務端對應版本的 oracle instant client(runtime 部分),安裝目錄為 ORACLE_CLIENT_HOME(這個環境變數也不是必須的,只是為了描述方便)。這個東東主要包含編譯驅動所需的標頭檔案和動態連結庫。安裝過程就不詳細說了,出現的各種錯誤提示都被我跳過了。選擇安裝 InstantClient 能找到後面執行需要的 .so。

安裝了 qt sdk 和 instant client 的機器以下簡稱 client,裝有 oracle 資料庫的機器為 server(當然這兩個可以是同一臺機器)。

編譯 QOCI 驅動

編譯工作在 client 上進行。

由於許可證的限制,qt 的開源版本並沒有帶編譯好的 oracle 驅動,但是原始碼中有編譯的程式碼,位於(把其中的版本號“4.8.1”替換成實際使用的版本號):

$QTDIR/QtSources/4.8.1/src/plugins/sqldrivers/oci

這個目錄下的 main.cpp 和 oci.pro 就是我們需要的程式碼。從 server 上的 $ORACLE_HOME/lib 中找到 libclntsh.so,libclntsh.so.10.1 和 libclntsh.so.11.1(其實這三個檔案是同一個東西,前兩個是連結到第三個的符號連結),把它們複製到這個目錄,然後在 oci.pro 中新增標頭檔案和庫的位置(最後 3 行):

TARGET = qsqloci

SOURCES = main.cpp
include(../../../sql/drivers/oci/qsql_oci.pri)

include(../qsqldriverbase.pri)

INCLUDEPATH+=$ORACLE_CLIENT_HOME/rdbms/public
INCLUDEPATH+=$QTDIR/QtSources/4.8.1/include
LIBS+= -L. -lclntsh

然後使用下面的命令編譯:

$QTDIR/Desktop/Qt/4.8.1/gcc/bin/qmake oci.pro
make

如果編譯成功會生成一個 libqsqloci.so,這個就是我們需要的驅動。

連線資料庫

測試是在 client 上進行的。測試程式放在 $ORACLE_TEST 目錄。

把上面生成的 libqsqloci.so 放到下面的目錄中:

$QTDIR/Desktop/Qt/4.8.1/gcc/plugins/sqldrivers

然後編寫測試程式(把其中的 dbhost,dbusr 和 dbpasswd 替換成實際的名字):

#include <QSqlDatabase>
#include <QSqlError>
#include <QDebug>
#include <QStringList>

int main(void)
{
    QSqlDatabase db; 

    QStringList drivers = QSqlDatabase::drivers();
    foreach (QString driver, drivers) 
        qDebug() << driver;

    db = QSqlDatabase::addDatabase("QOCI");
    db.setDatabaseName("orcl"); /* default */
    db.setPort(1521);

    db.setHostName("<dbhost>");
    db.setUserName("<dbusr>");
    db.setPassword("<dbpasswd>");

    if (db.open())
        qDebug() << "connect ok";
    else
        qDebug() << db.lastError().text();

    return 0;
}

關鍵時刻到了。先看編譯程式的 Makefile:

QTPATH := $(QTDIR)/Desktop/Qt/4.8.1/gcc
INCLUDE := -I$(QTPATH)/include -I$(QTPATH)/include/QtCore -I$(QTPATH)/include/QtSql
LIBS := -L$(QTPATH)/lib -lQtCore -lQtSql -L. -lclntsh

TARGET := oracletest

$(TARGET): oracletest.o
        g++ -o [email protected] $^ $(LIBS)

.cpp.o:
        g++ -c $< $(INCLUDE)

clean:
        rm -f *.o $(TARGET)

然後設定環境變數:

export ORACLE_HOME=$ORACLE_CLIENT_HOME
export LD_LIBRARY_PATH=$QTDIR/Desktop/Qt/4.8.1/gcc/lib:$ORACLE_HOME/lib:$LD_LIBRARY_PATH

雖然這是在 client 端,但是還是要設定 ORACLE_HOME(沒錯,client 端的環境變數也叫這個,如果不設定會出現“QOCIDriver: unable to create environment”的錯誤提示,解決這個問題花了我一下午的時間)。

(2012.09.05 補充)我安裝的時候使用的是 oracle client 的完整安裝包,安裝介面上包含 4 個選項:InstantClient,Administrator,Runtime 和 Custom。如果選了 InstantClient 能找到上面提到的幾個 .so,但是執行的時候同樣會提示錯誤“QOCIDriver: unable to create environment”,還要重新裝 Runtime,並且在設定環境變數的時候把 ORACLE_HOME 設為 Runtime 部分的安裝目錄而不是 InstantClient 的目錄。

然後編譯執行:

make && ./oracletest

如果一切順利,最後看到的輸出類似於下面這樣:

"QSQLITE" 
"QOCI8" 
"QOCI" 
connect ok 

後記

寫這篇筆記也就用了 1 小時多點,但是這幾天的經歷和心情卻是很痛苦,其中走了多少彎路浪費了多少時間。作為一個使用過 LFS 和 FVWM 的使用者,這兩次折騰讓我最不能明白的是,像 oracle 這種反社會反人類反科學的軟體怎麼會一直存在並活得好好的。

參考資料

[1]QOCI for the Oracle Call Interface (OCI)
[2]QOCI編譯筆記

軟體使用和配置oracleqt

Comment (1)

  1. lei

    2012 年 8 月 10 日 10:11:39

    Oracle和微軟策略類似,用準盜版方式培育市場(軟體安裝media可以從官網下載,並且沒有多少限制,只是沒有補丁,對行業標杆使用者進行超低價重點培育等),形成了廣泛的開發和使用人員隊伍,並形成技術輿論影響,一旦有了大批靠他吃飯的,就成功了。
    BTW,目前我也靠他吃飯。