1. 程式人生 > >對Qt5.4連線Oracle資料的一點看法

對Qt5.4連線Oracle資料的一點看法

        剛學Qt,對它的訊號、槽機制打動;一直想寫個記賬程式,手頭上有個現成的Oracle資料,就用它做後臺吧。

       其實,一直懂Qt連線Oracle資料,上網看了下,公共版不帶Oracle驅動,要自己編譯;好吧,就來看下怎麼編譯吧:(跟著大部分人編譯的歷程,是能編譯成功的。)我在Win7下編譯。編譯需要的標頭檔案[.h]、靜態庫檔案[.lib] ,其實不一定要安裝Oracle資料庫或客氣端,只要去Oracle官網上下載 "instantclient-sdk-nt*.zip" 檔案就可以了,裡面就有編譯所需的檔案了。編譯中要注意一點:需要在 oci.pro 這個工程檔案里加上 "INCLUDEPATH += < "oci.h目錄"> 、   LIBS += -L

< "oci.lib資料夾"> ,做好這些,想怎麼編譯就怎麼編譯。

      說完編譯,就說下重要的連線。連線,這是個困擾我好兩週的問題:因為不知道連線,只能參看幫助裡的例子,發現連線只有"mysql"的連線;再看網上連線,一個樣子;這裡我就在想用這種模式,非得知道Oracle資料的主機IP、埠、資料庫名稱才能連線,那這樣用Oracle連線名那種安全、方便的連線方式不是就無用武之地了嗎?! 我想這種方式不好,不方便,不安全,得找辦法取代這模式。我最初從驅動檔案入手,想用改開啟資料邊引數入手,結果提示 “ORA-12162: TNS: 指定的服務名不正確”、“ORA-12336: 不能連線到資料庫 (連結名稱 )” 這樣不行;我動過封閉OCI,就像封閉OCCI一樣,可是,對OCI不工作流程不熟,在網上看了好多封裝過程,還是沒明白,甚至看官方的OCI說明書,對與我種一句英文句子,10個單詞,我只知道1個的我,這個工作量太;後來想參看封裝OCCI,可是沒找到裝的原始碼做參考,最終放棄了;不行,還是得從Qt入手,針對連線資料庫功能下手,雖然不明白怎麼連線,但問題就出在那個連線的地方;上程式碼:(程式碼片段不能用,直接寫了)

bool QOCIDriver::open(const QString & db,
                       const QString & user,
                       const QString & password,
                       const QString & hostname,
                       int port,
                       const QString &opts)
{
    Q_D(QOCIDriver);
    int r;

    if (isOpen())
        close();

    qParseOpts(opts, d);

    // Connect without tnsnames.ora if a hostname is given
    QString connectionString = db;
    if (!hostname.isEmpty())
        connectionString =
        QString::fromLatin1("(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=%1)(Port=%2))"
                "(CONNECT_DATA=(SID=%3)))").arg(hostname).arg((port > -1 ? port : 1521)).arg(db);

    r = OCIHandleAlloc(d->env, reinterpret_cast<void **>(&d->srvhp), OCI_HTYPE_SERVER, 0, 0);
    if (r == OCI_SUCCESS)
        r = OCIServerAttach(d->srvhp, d->err, reinterpret_cast<const OraText *>(connectionString.utf16()),
                            connectionString.length() * sizeof(QChar), OCI_DEFAULT);

一直以為是引數太多,不方便,看上面的程式碼發現,還真是每個引數都必須的;一直改那些引數的地方;無果。最後發現

   QString connectionString = db;
    if (!hostname.isEmpty())
        connectionString =
            QString::fromLatin1("(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=%1)(Port=%2))"
                "(CONNECT_DATA=(SID=%3)))").arg(hostname).arg((port > -1 ? port : 1521)).arg(db);

關鍵點: if (!hostname.isEmpty()),看明白吧,“hostname” 是可以不要的,只要 “hostname” 引數不傳入,就不需要寫IP、埠……。

上面的程式碼是一樣的功能,取得“QString connectionString”,這下明白了,連線時不傳入引數 “hostname” ;

這下可以一個一個引數試了,一共也就五個引數,去掉 "tnsnames.ora" 封裝好的三個引數, 也就只要三個引數(username, Password, "tnsnames.ora ->  <Connname> " )。

這下問題解決了。上程式碼:

    QSqlDatabase db = QSqlDatabase::addDatabase("QOCI8");


    //db.setHostName("IP");
    db.setUserName("user");
    db.setPassword("aa");
    //db.setPort(1521);
    db.setDatabaseName("test");

  if(!db.open())
    {

       QMessageBox::information(NULL, "ErrorInfo", db.lastError().text(), QMessageBox::Ok);
        qDebug() << db.lastError().text();
        return;
    }

       QMessageBox::information(NULL, "Conn", "Connect Success! ", QMessageBox::Ok);
        qDebug() << db.lastError().text();

     ……

……