天天看點

關于Qt資料庫開發的一些冷知識

一、知識要點

  • Qt即支援庫的形式直接和資料庫通信,也支援ODBC資料源的形式和各種資料庫通信,這樣就涵蓋了所有的情況。
  • Qt資料庫程式打包釋出,所有前提:注意區分32/64位,你的程式是32位的就必須帶上32位的庫,64位的必須帶上64位的庫,這點Qt的庫也是這個要求。mysql釋出最簡單,帶上一個mysql的動态庫檔案就行(windows上的是libmysql.dll),非常簡單。sqlserver不用帶,因為是微軟的親兒子,一般作業系統自帶。postgres需要帶上libpq.dll、libintl-8.dll、libiconv-2.dll、libeay32.dll、ssleay32.dll這幾個檔案就行。oracle需要帶上oci.dll、oraociei11.dll(這個檔案很大有130MB+),如果不行建議直接安裝個oracle client用戶端軟體,然後對應bin目錄設定到環境變量就好。
  • 打包釋出後測試下來,發現32位的程式也可以正常連接配接64位的mysql,64位的程式也可以正常連接配接32位的mysql,是以判斷隻要和程式的庫的位數一緻就行(編譯的時候也是這個規則,32位的Qt程式編譯資料庫插件也要用32位的資料庫連結庫。),不需要和具體的資料庫的位數一緻,測試過mysql、sqlserver、postgresql資料庫都是類似規則。
  • 大量測試對比下來,通過odbc資料源的方式和直連資料庫的方式批量插入大量資料記錄,直連方式速度更快,約5%左右,是以建議盡量采用此方式,是在沒有此方式的環境才采用odbc資料源的方式,Qt預設自帶odbc資料庫插件。
  • mysql、postgresql資料庫在執行sql腳本的時候,會自動将表名和字段名全部轉成小寫,oracle全部轉成大寫,這就導緻使用QSqlTableModel調用setTable設定資料庫表名的時候,一定要和資料庫中的表名一緻,區分大小寫,mysql資料庫預設配置設定的不區分大小寫是以沒有這個問題,是以就是在對postgresql和oracle資料庫的時候一定要注意,本人就是在這裡卡了很久,差點要把這巨大的屎盆扣在Qt的BUG上。
void DbHelper::bindTable(const QString &dbType, QSqlTableModel *model, const QString &table)
{
    //postgresql全部小寫,oracle全部大寫,這兩個資料庫嚴格區分表名字段名的大小寫卧槽
    QString flag = dbType.toUpper();
    if (flag == "POSTGRESQL") {
        model->setTable(table.toLower());
    } else if (flag == "ORACLE") {
        model->setTable(table.toUpper());
    } else {
        model->setTable(table);
    }
}      
  • Qt支援不指定資料庫名打開資料庫,因為有時候是要在連接配接資料庫伺服器後,執行sql語句建立資料庫。資料庫都還沒存在怎麼連接配接呢,測試發現sqlite、mysql、sqlserver、postgresql都支援這個特性。在删除和建立資料庫的前提是該資料庫沒有被其他程式占用,比如其他程式已經打開了該資料庫則會執行失敗。這裡我就折磨過很多次,為什麼執行失敗呢?後面發現第三方資料庫工具已經打開了該資料庫,把工具關掉就ok了。
QSqlDatabase database = QSqlDatabase::addDatabase("QMYSQL");
//database.setDatabaseName("dbtool");
database.setHostName("127.0.0.1");
database.setPort(3306);
database.setUserName("root");
database.setPassword("root");

if (database.open()) {
    QSqlQuery query(database);
    qDebug() << "删除資料庫" << query.exec("drop database dbtool");
    qDebug() << "建立資料庫" << query.exec("create database dbtool");
    if (query.exec("select * from userinfo")) {
        while (query.next()) {
            qDebug() << "查詢資料庫" << query.value(0);
        }
    }
} else {
     qDebug() << "打開資料庫" << database.lastError().text();
}      
  • 用QSqlQueryModel+QTableView顯示資料,int類型的資料,如果超過100萬,會變成科學計數顯示,這就很惱火了,肯定不是自己想要的結果。找遍網絡搜尋,終于找到一個同樣問題的哥們,需要對這一列加個空的委托就行。後面發現空委托也不行,超過1000萬條又屌樣了,需要終極大法重載資料模型顯示。
ui->tableView->setItemDelegateForColumn(0, new QItemDelegate);

//下面是終極大法
QVariant SqlQueryModel::data(const QModelIndex &index, int role) const
{
    QVariant value = QSqlQueryModel::data(index, role);
    //超過100萬的數值會被科學計數顯示需要這裡轉成字元串顯示
    if (role == Qt::DisplayRole) {
        int result = value.toInt();
        if (result >= 1000000) {
            value = QString::number(result);
        }
    }
    return value
}      
  • mysql資料庫有多種資料庫引擎,其中MyIsam不支援資料庫事務,預設一般是這個引擎,是以當你使用Qt中的transaction方法後commit送出時候,會發現不成功,其實事實上又是成功的,去資料庫裡面檢視對應的結果又是正确的。有兩個辦法,第一就是将資料庫引擎改成InnoDB,第二就是在送出後做個錯誤判斷 if (database.commit() || !database.lastError().isValid()) ,錯誤不可用也說明是成功的。
  • 如果采用odbc資料源通信,則隻需設定資料庫名稱setDatabaseName、設定使用者名稱setUserName、設定使用者密碼setPassword這三個參數即可,因為資料源配置的時候就已經設定好對應的主機位址和端口以及關聯的資料庫名稱,是以在用odbc資料源通信的時候隻需要再次驗證使用者資訊即可。這裡特别要注意的是setDatabaseName設定資料庫名稱要填寫資料源配置的名稱。
  • 經過大量的對比測試,包括插入、删除、批量、查詢、分頁等操作,千萬量級資料,在Qt資料庫部分響應速度這塊,友好度排名依次是 sqlite > postgresql > oracle > mysql > odbc 。千萬量級以上是 postgresql > oracle > mysql > sqlite > odbc 。億級别以上是 oracle > postgresql > 其他。以上測試均建立在初學者水準基礎上,至于分庫分表、聯合查詢、緩存、記憶體資料庫等各種進階知識點沒用上。

二、相關位址

  1. 體驗位址:​​https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A​​ 提取碼:o05q 檔案名:bin_dbtool.zip
  2. 國内站點:​​https://gitee.com/feiyangqingyun​​
  3. 國際站點:​​https://github.com/feiyangqingyun​​
  4. 知乎首頁:​​https://www.zhihu.com/people/feiyangqingyun/​​