對Qt5.4連線Oracle資料的一點看法
剛學Qt,對它的訊號、槽機制打動;一直想寫個記賬程式,手頭上有個現成的Oracle資料,就用它做後臺吧。
其實,一直懂Qt連線Oracle資料,上網看了下,公共版不帶Oracle驅動,要自己編譯;好吧,就來看下怎麼編譯吧:(跟著大部分人編譯的歷程,是能編譯成功的。)我在Win7下編譯。編譯需要的標頭檔案[.h]、靜態庫檔案[.lib] ,其實不一定要安裝Oracle資料庫或客氣端,只要去Oracle官網上下載 "instantclient-sdk-nt*.zip" 檔案就可以了,裡面就有編譯所需的檔案了。編譯中要注意一點:需要在 oci.pro 這個工程檔案里加上 "INCLUDEPATH += < "oci.h目錄"> 、 LIBS += -L
說完編譯,就說下重要的連線。連線,這是個困擾我好兩週的問題:因為不知道連線,只能參看幫助裡的例子,發現連線只有"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();
……
……