QT SQL

數(shù)據(jù)庫相關(guān)類

類名 描述
QSqlDatabase 代表一個(gè)數(shù)據(jù)庫鏈接
QSqlDriverCreator 為特定的驅(qū)動(dòng)類型提供SQL驅(qū)動(dòng)的模板工廠類
QSqlDriverCreatorBase QSqlDriverCreator的基類
QSqlDriver 用于訪問特定SQL數(shù)據(jù)庫的抽象基類
QSqlError SQL 數(shù)據(jù)庫錯(cuò)誤信息
QSqlField 操作SQL數(shù)據(jù)庫表和視圖中的字段
QSqlIndex 操作和描述數(shù)據(jù)庫索引
QSqlQuery 執(zhí)行和操作SQL語句
QSqlRecord 封裝數(shù)據(jù)庫記錄
QSqlResult 用于從特定SQL數(shù)據(jù)庫訪問數(shù)據(jù)的抽象界面
QSql 包含整個(gè)Qt SQL模塊中使用的標(biāo)識(shí)符
QSqlQueryModel SQL結(jié)果集的只讀數(shù)據(jù)模型
QSqlRelationalTableModel 用于單個(gè)數(shù)據(jù)庫表的可編輯數(shù)據(jù)模型亮曹,具有外鍵支持
QSqlTableModel 單個(gè)數(shù)據(jù)庫表的可編輯數(shù)據(jù)模型

數(shù)據(jù)庫相關(guān)類分為三個(gè)層次:

  • 驅(qū)動(dòng)層:
    QSqlDriver,QSqlDriverCreator,QSqlDriverCreatorBase,QSqlDriverPlugin,QSqlResult.此層次為特定數(shù)據(jù)庫和SQL API之間提供了低級(jí)的溝通橋梁.
  • SQL API層:
    QSqlDatabase,QSqlQuery,QSqlError,QSqlField,QSqlIndex,QSqlRecord.此層此提供對數(shù)據(jù)庫的訪問.
  • 用戶界面層:
    QSqlQueryModel, QSqlTableModel, QSqlRelationalTableModel.此層次將數(shù)據(jù)從數(shù)據(jù)庫顯示在widget上,要配合Qt的 model/view框架使用.

連接到數(shù)據(jù)庫

在訪問數(shù)據(jù)庫之前需要先創(chuàng)建并打開一個(gè)或多個(gè)數(shù)據(jù)庫鏈接.數(shù)據(jù)庫鏈接由鏈接名稱來區(qū)分,不由數(shù)據(jù)庫名稱區(qū)分.同一個(gè)數(shù)據(jù)庫上可以有多個(gè)數(shù)據(jù)庫鏈接.
注意創(chuàng)建鏈接和打開鏈接的區(qū)別:創(chuàng)建鏈接涉及到QSqlDatabase的實(shí)例化.連接在打開之前是不可用的,需要調(diào)用open()函數(shù)來打開它.

QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("bigblue");
db.setDatabaseName("flightdb");
db.setUserName("acarlson");
db.setPassword("1uTbSbAs");
bool ok = db.open();

第一句創(chuàng)建鏈接,最后一句打開鏈接,中間語句設(shè)置鏈接的各種參數(shù),包括主機(jī)名,數(shù)據(jù)庫名,數(shù)據(jù)庫用戶名,數(shù)據(jù)庫密碼等.第一句中的參數(shù)"QMYSQL"指明我們使用MySQL數(shù)據(jù)庫,鏈接名稱為空(默認(rèn)鏈接).
如果發(fā)生錯(cuò)誤請使用QSqlDatabase::lastError()來獲取錯(cuò)誤信息.
使用QSqlDatabase::database()來獲取已經(jīng)創(chuàng)建的鏈接.
要?jiǎng)h除一個(gè)數(shù)據(jù)庫鏈接,先調(diào)用close()再調(diào)用removeDatabase().

SQL數(shù)據(jù)庫驅(qū)動(dòng)

Qt SQL模塊使用驅(qū)動(dòng)插件來和不同的數(shù)據(jù)庫API進(jìn)行通訊.因?yàn)镼t SQL模塊API是"數(shù)據(jù)庫獨(dú)立的",所有的數(shù)據(jù)庫特異化操作代碼都被包含在各自對應(yīng)的驅(qū)動(dòng)中.Qt SQL模塊已經(jīng)支持一些驅(qū)動(dòng)了,并且你也可以自己添加數(shù)據(jù)庫驅(qū)動(dòng).下表為已經(jīng)支持的驅(qū)動(dòng):

驅(qū)動(dòng)名稱 描述
QDB2 IBM DB2 (version 7.1 and above)
QIBASE Borland InterBase
QMYSQL MySQL
QOCI Oracle Call Interface Driver
QODBC Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases
QPSQL PostgreSQL (versions 7.3 and above)
QSQLITE2 SQLite version 2
QSQLITE SQLite version 3
QTDS Sybase Adaptive Server Note: obsolete from Qt 4.7

執(zhí)行SQL語句

QSqlQuery類為執(zhí)行SQL語句和遍歷執(zhí)行結(jié)果集提供了接口.

QSqlQuery query;
query.exec("SELECT name, salary FROM employee WHERE salary > 50000");

QSqlQuery的構(gòu)造函數(shù)可以接收一個(gè)QSqlDatabase對象,以此來指定SQL語句要使用的數(shù)據(jù)庫鏈接.如果沒有提供QSqlDatabase對象,SQL語句會(huì)在默認(rèn)鏈接上執(zhí)行.如果有錯(cuò)誤exec()函數(shù)會(huì)返回fasle.使用QSqlQuery::laseError()獲取錯(cuò)誤信息.

遍歷結(jié)果集合:

QSqlQuery允許每次訪問一條結(jié)果集中的記錄.調(diào)用exec()函數(shù)后QSqlQuery的內(nèi)部指針位于第一個(gè)記錄的前一個(gè)位置,在訪問第一條記錄之前必須要調(diào)用QSqlQuery::next(),依次重復(fù)知道next()函數(shù)返回值為false.

 while (query.next()) {
        QString name = query.value(0).toString();
        int salary = query.value(1).toInt();
        qDebug() << name << salary;
 }

QSqlQuery::value() 返回當(dāng)前記錄中的字段值,返回值是QVariant類型的.
結(jié)果集合遍歷函數(shù)列表:

函數(shù)名稱 描述
QSqlQuery::next() 下一條記錄
QSqlQuery::previous() 上一條記錄
QSqlQuery::first() 第一條記錄
QSqlQuery::last() 最后一條記錄
QSqlQuery::seek() 跳到指定記錄
QSqlQuery::at() 當(dāng)前記錄索引
QSqlQuery::size() 總記錄條數(shù)
QSqlDriver::hasFeature() 當(dāng)前類型的數(shù)據(jù)庫是否支持某種操作特性
QSqlQuery query;
int numRows;
query.exec("SELECT name,salary FROM employee WHERE salary > 50000");

QSqlDatabase defaultDB = QSqlDatabase::database();
if(defaultDB.driver()->hasFeature(QSqlDriver::QuerySize))
{
    numRows = query.size;
}
else
{
    query.last();
    numRows = query.at()+1;
}

如果僅使用next()和seek()的正值進(jìn)行迭代目派,則可以在調(diào)用exec()之前調(diào)用QSqlQuery :: setForwardOnly(true). 這是一個(gè)簡單的優(yōu)化,可以加快大型結(jié)果集上的查詢速度庵佣。

插入,更新,刪除記錄

QSqlQuery可執(zhí)行任意的SQL語句,而不止SELECT語句.

插入示例

QSqlQuery query;
query.exec("INSERT INTO employee(id,name,salary) "
                  "VALUES (1001,'Thad Beaumont',65000)");

如果希望插入多條記錄,將SQL語句和實(shí)際要插入的值分開來寫是更高效的,這可以使用占位符來實(shí)現(xiàn),Qt支持兩種格式的占位符,名稱綁定和位置綁定.

  • 名稱綁定示例
QSqlQuery query;
query.prepare("INSERT INTO employee (id, name, salary) "
                    "VALUES (:id, :name, :salary)");
query.bindValue(":id", 1001);
query.bindValue(":name", "Thad Beaumont");
query.bindValue(":salary", 65000);
query.exec();
  • 位置綁定示例
QSqlQuery query;
query.prepare("INSERT INTO employee (id, name, salary) "
                    "VALUES (?, ?, ?)");
query.addBindValue(1001);
query.addBindValue("Thad Beaumont");
query.addBindValue(65000);
query.exec();

這兩種語法適用于Qt提供的所有數(shù)據(jù)庫驅(qū)動(dòng)程序,如果數(shù)據(jù)庫本身支持此語法,Qt將查詢轉(zhuǎn)發(fā)給DBMS,否則Qt會(huì)通過預(yù)處理來模擬占位符語法.最終由DBMS執(zhí)行的SQL語句可以通過QSqlQuery::ecutQuery()獲取.
插入多條記錄時(shí)只需要調(diào)用一次QSqlQuery::prepare(),然后可以按照你的需要重復(fù)多次調(diào)用bindValue()或者addBindValue() 和exec().

更新示例

QSqlQuery query;
query.exec("UPDATE employee SET salary = 70000 WHERE id = 1003");

同樣,更新時(shí)也可以使用名稱或者位置占位符.

刪除示例

QSqlQuery query;
query.exec("DELETE FROM employee WHERE id = 1007");

判斷表是否存在

bool isTableExists(QString tableName)
{
      QSqlDatabase db = QSqlDatabase::database();          // 假設(shè)數(shù)據(jù)庫連接已經(jīng)成功打開
      QStringList tableList = db.tables(QSql::AllTables);
      return tableList.contains(tableName);
}

數(shù)據(jù)庫事務(wù)

如果底層數(shù)據(jù)庫引擎支持事務(wù),QSqlDriver::hasFeature(QSqlDriver::Transactions)會(huì)返回true.調(diào)用QSqlDatabase::transaction()來啟動(dòng)事務(wù),后面跟著你想在事務(wù)上下文中完成的SQL語句,然后執(zhí)行QSqlDatabase::commit()或者QSqlDatabase::rollback().使用事務(wù)時(shí)必須要在創(chuàng)建query前開啟事務(wù).

QSqlDatabase::database().transaction();
QSqlQuery query;
query.exec("SELECT id FROM employee WHERE name = 'Torild Halvorsen'");
if (query.next()) {
    int employeeId = query.value(0).toInt();
    query.exec("INSERT INTO project (id, name, ownerid) "
               "VALUES (201, 'Manhattan Project', "
               + QString::number(employeeId) + ')');
}
QSqlDatabase::database().commit();

事務(wù)用于保證復(fù)雜的操作的原子性.

使用SQL模型類

除了QSqlQuery之外,Qt提供三個(gè)高級(jí)類來訪問數(shù)據(jù)庫:

類名 描述
QSqlQueryModel 基于任意SQL查詢的只讀模型
QSqlTableModel 單獨(dú)一張表上的讀寫模型
QSqlRelationalTableModel 具有外鍵支持的QSqlTableModel

這些類繼承自QAbstractTableModel(進(jìn)一步繼承自QAbstractItemModel),這使得在諸如QListView和QTableView視圖類中呈現(xiàn)數(shù)據(jù)庫中的數(shù)據(jù)變得簡單.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末满哪,一起剝皮案震驚了整個(gè)濱河市婿斥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翩瓜,老刑警劉巖受扳,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異兔跌,居然都是意外死亡勘高,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門坟桅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來华望,“玉大人,你說我怎么就攤上這事仅乓±抵郏” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵夸楣,是天一觀的道長宾抓。 經(jīng)常有香客問我,道長豫喧,這世上最難降的妖魔是什么石洗? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮紧显,結(jié)果婚禮上讲衫,老公的妹妹穿的比我還像新娘。我一直安慰自己孵班,他們只是感情好涉兽,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著篙程,像睡著了一般枷畏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虱饿,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天拥诡,我揣著相機(jī)與錄音丹允,去河邊找鬼。 笑死袋倔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的折柠。 我是一名探鬼主播宾娜,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扇售!你這毒婦竟也來了前塔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤承冰,失蹤者是張志新(化名)和其女友劉穎华弓,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體困乒,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寂屏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了娜搂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迁霎。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖百宇,靈堂內(nèi)的尸體忽然破棺而出考廉,到底是詐尸還是另有隱情,我是刑警寧澤携御,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布昌粤,位于F島的核電站,受9級(jí)特大地震影響啄刹,放射性物質(zhì)發(fā)生泄漏涮坐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一鸵膏、第九天 我趴在偏房一處隱蔽的房頂上張望膊升。 院中可真熱鬧,春花似錦谭企、人聲如沸廓译。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽非区。三九已至,卻和暖如春盹廷,著一層夾襖步出監(jiān)牢的瞬間征绸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留管怠,地道東北人淆衷。 一個(gè)月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像渤弛,于是被迫代替她去往敵國和親祝拯。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容