數(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ù)變得簡單.