[Qt教程] 第23篇 数据库(三)利用QSqlQuery类执行SQL语句
生活随笔
收集整理的這篇文章主要介紹了
[Qt教程] 第23篇 数据库(三)利用QSqlQuery类执行SQL语句
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
[Qt教程]?第23篇 數(shù)據(jù)庫(kù)(三)利用QSqlQuery類(lèi)執(zhí)行SQL語(yǔ)句
??|?查看: 813|?回復(fù): 0| 利用QSqlQuery類(lèi)執(zhí)行SQL語(yǔ)句 版權(quán)聲明 該文章原創(chuàng)于作者yafeilinux,轉(zhuǎn)載請(qǐng)注明出處! 導(dǎo)語(yǔ) SQL即結(jié)構(gòu)化查詢(xún)語(yǔ)言,是關(guān)系數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn)語(yǔ)言。前面兩節(jié)中已經(jīng)在Qt里利用QSqlQuery類(lèi)執(zhí)行了SQL語(yǔ)句,這一節(jié)我們將詳細(xì)講解該類(lèi)的使用。需要說(shuō)明,因?yàn)槲覀冎卦谥v解Qt中的數(shù)據(jù)庫(kù)使用,而非專(zhuān)業(yè)的講解數(shù)據(jù)庫(kù)知識(shí),所以不會(huì)對(duì)數(shù)據(jù)庫(kù)中的一些知識(shí)進(jìn)行深入講解。 環(huán)境:Windows Xp + Qt 4.8.4+Qt Creator2.6.2 目錄 一、創(chuàng)建數(shù)據(jù)庫(kù)連接 二、操作結(jié)果集 三、在SQL語(yǔ)句中使用變量 四、批處理操作 五、事務(wù)操作 正文 一、創(chuàng)建數(shù)據(jù)庫(kù)連接 前面我們是在主函數(shù)中創(chuàng)建數(shù)據(jù)庫(kù)連接,然后打開(kāi)并使用。實(shí)際中為了明了方便,一般將數(shù)據(jù)庫(kù)連接單獨(dú)放在一個(gè)頭文件中。下面來(lái)看一個(gè)例子。 1.新建Qt Gui應(yīng)用,項(xiàng)目名稱(chēng)為myquery,基類(lèi)為QMainWindow,類(lèi)名為MainWindow。完成后打開(kāi)myquery.pro并將第一行代碼更改為: QT? ?? ??+= coregui sql 然后保存該文件。 2.向項(xiàng)目中添加新的C++頭文件,名稱(chēng)為connection.h,然后打開(kāi)該文件,更改如下: #ifndef?CONNECTION_H #define?CONNECTION_H #include?<QMessageBox> #include?<QSqlDatabase> #include?<QSqlQuery> static?bool?createConnection() { ? ??QSqlDatabase?db?=?QSqlDatabase::addDatabase("QSQLITE"); ? ??db.setDatabaseName(":memory:"); ? ??if?(!db.open())?{ ? ?? ??QMessageBox::critical(0,?qApp->tr("Cannot open database"), ? ?? ?? ???qApp->tr("Unable to establisha database connection." ? ?? ?? ?? ?? ?? ?? ?),?QMessageBox::Cancel); ? ?? ??return?false; ? ??} ? ??QSqlQuery?query; ? ??query.exec("create table student (id int primary key, " ? ?? ?? ?? ?? ?"name varchar(20))"); ? ??query.exec("insert into student values(0, 'first')"); ? ??query.exec("insert into student values(1, 'second')"); ? ??query.exec("insert into student values(2, 'third')"); ? ??query.exec("insert into student values(3, 'fourth')"); ? ??query.exec("insert into student values(4, 'fifth')"); ? ??return?true; } #endif?// CONNECTION_H 在這個(gè)頭文件中我們添加了一個(gè)建立連接的函數(shù),使用這個(gè)頭文件的目的就是要簡(jiǎn)化主函數(shù)中的內(nèi)容。這里先創(chuàng)建了一個(gè)SQLite數(shù)據(jù)庫(kù)的默認(rèn)連接,設(shè)置數(shù)據(jù)庫(kù)名稱(chēng)時(shí)使用了“:memory:”,表明這個(gè)是建立在內(nèi)存中的數(shù)據(jù)庫(kù),也就是說(shuō)該數(shù)據(jù)庫(kù)只在程序運(yùn)行期間有效,等程序運(yùn)行結(jié)束時(shí)就會(huì)將其銷(xiāo)毀。當(dāng)然,大家也可以將其改為一個(gè)具體的數(shù)據(jù)庫(kù)名稱(chēng),比如“my.db”,這樣就會(huì)在項(xiàng)目目錄中創(chuàng)建該數(shù)據(jù)庫(kù)文件了。下面使用open()函數(shù)將數(shù)據(jù)庫(kù)打開(kāi),如果打開(kāi)失敗,則彈出提示對(duì)話框。最后使用QSqlQuery創(chuàng)建了一個(gè)student表,并插入了包含id和name兩個(gè)屬性的五條記錄,如下圖所示。其中,id屬性是int類(lèi)型的,“primary key”表明該屬性是主鍵,它不能為空,而且不能有重復(fù)的值;而name屬性是varchar類(lèi)型的,并且不大于20個(gè)字符。這里使用的SQL語(yǔ)句都要包含在雙引號(hào)中,如果一行寫(xiě)不完,那么分行后,每一行都要使用兩個(gè)雙引號(hào)引起來(lái)。 需要注意,代碼中的query沒(méi)有進(jìn)行任何指定就可以操作前面打開(kāi)的數(shù)據(jù)庫(kù),這是因?yàn)楝F(xiàn)在只有一個(gè)數(shù)據(jù)庫(kù)連接,它就是默認(rèn)連接,這時(shí)候所有的操作都是針對(duì)該連接的。但是如果要同時(shí)操作多個(gè)數(shù)據(jù)庫(kù)連接,就需要進(jìn)行指定了,這方面內(nèi)容可以參考《Qt Creator快速入門(mén)》的第17章。 3.下面我們到main.cpp中調(diào)用連接函數(shù)。 #include?"mainwindow.h" #include?<QApplication> #include?"connection.h" int?main(int?argc,?char?*argv[]) { ? ??QApplication?a(argc,?argv); ? ? ? ??if?(!createConnection()) ? ?? ?? ???return?1; ? ? ? ??MainWindow?w; ? ??w.show(); ? ? ? ??return?a.exec(); } 4.我們往界面上添加一個(gè)按鈕來(lái)實(shí)現(xiàn)查詢(xún)操作。雙擊mainwindow.ui文件進(jìn)入設(shè)計(jì)模式。然后將一個(gè)Push Button拖到界面上,并修改其顯示文本為“查詢(xún)”。效果如下圖所示。 5.在查詢(xún)按鈕上點(diǎn)擊鼠標(biāo)右鍵,選擇“轉(zhuǎn)到槽”,然后選擇clicked()單擊信號(hào)槽并點(diǎn)擊確定,如下圖所示。 6.將槽的內(nèi)容更改如下: void?MainWindow::on_pushButton_clicked() { ? ??QSqlQuery?query; ? ??query.exec("select * from student"); ? ??while(query.next()) ? ??{ ? ?? ??qDebug()?<<?query.value(0).toInt() << query.value(1).toString(); ? ??} } 7.在mainwindow.cpp文件中添加頭文件: #include?<QSqlQuery> #include?<QDebug> 8.運(yùn)行程序,然后按下查詢(xún)按鈕,在應(yīng)用程序輸出窗口將會(huì)輸出結(jié)果,效果如下圖所示。 二、操作結(jié)果集 在前面的程序中,我們使用query.exec("select * from student");查詢(xún)出表中所有的內(nèi)容。其中的SQL語(yǔ)句“select * from student”中“*”號(hào)表明查詢(xún)表中記錄的所有屬性。而當(dāng)query.exec("select * from student");這條語(yǔ)句執(zhí)行完后,我們便獲得了相應(yīng)的執(zhí)行結(jié)果,因?yàn)楂@得的結(jié)果可能不止一條記錄,所以稱(chēng)之為結(jié)果集。 結(jié)果集其實(shí)就是查詢(xún)到的所有記錄的集合,在QSqlQuery類(lèi)中提供了多個(gè)函數(shù)來(lái)操作這個(gè)集合,需要注意這個(gè)集合中的記錄是從0開(kāi)始編號(hào)的。最常用的操作有:
最后在mainwindow.cpp中添加#include?<QSqlRecord>頭文件包含,運(yùn)行程序,點(diǎn)擊查詢(xún)按鈕,輸出結(jié)果如下圖所示。 三、在SQL語(yǔ)句中使用變量 1.我們先來(lái)看一個(gè)例子。首先在設(shè)計(jì)模式往界面上添加一個(gè)Spin Box部件,如下圖所示。 2.將查詢(xún)按鈕槽里面的內(nèi)容更改如下: void?MainWindow::on_pushButton_clicked() { ? ??QSqlQuery?query; ? ??int?id?=?ui->spinBox->value(); ? ??query.exec(QString("select name from student where id =%1") ? ?? ?? ?? ?? ?.arg(id)); ? ??query.next(); ? ??QString?name?=?query.value(0).toString(); ? ??qDebug()?<<?name; } 這里使用了QString類(lèi)的arg()函數(shù)實(shí)現(xiàn)了在SQL語(yǔ)句中使用變量,我們運(yùn)行程序,更改Spin Box的值,然后點(diǎn)擊查詢(xún)按鈕,效果如下圖所示。 3.其實(shí)在QSqlQuery類(lèi)中提供了數(shù)據(jù)綁定同樣可以實(shí)現(xiàn)在SQL語(yǔ)句中使用變量,雖然它也是通過(guò)占位符來(lái)實(shí)現(xiàn)的,不過(guò)使用它形式上更明了一些。下面先來(lái)看一個(gè)例子,將查詢(xún)按鈕槽更改如下: 也可以利用addBindValue()函數(shù),這樣就可以省去編號(hào),它是按順序給屬性賦值的,如下: query.prepare("insert into student(id, name) " ? ?? ?? ?? ?? ?? ?"values (?, ?)"); query.addBindValue(5); query.addBindValue("sixth"); query.exec(); 當(dāng)用ODBC的表示方法時(shí),我們也可以將編號(hào)用實(shí)際的占位符代替,如下: query.prepare("insert into student(id, name) " ? ?? ?? ?? ?? ?? ?? ??"values (:id, :name)"); query.bindValue(":id", 5); query.bindValue(":name", "sixth"); query.exec(); 以上各種形式的表示方式效果是一樣的。 4.下面我們演示一下通過(guò)綁定操作在SQL語(yǔ)句中使用變量。更改槽函數(shù)如下: void?MainWindow::on_pushButton_clicked() { ? ??QSqlQuery?query; ? ??query.prepare("select name from student where id = ?"); ? ??int?id?=?ui->spinBox->value(); ? ??query.addBindValue(id); ? ??query.exec(); ? ??query.next(); ? ??qDebug()?<<?query.value(0).toString(); } 運(yùn)行程序,可以實(shí)現(xiàn)通過(guò)Spin Box的值來(lái)進(jìn)行查詢(xún)。 四、批處理操作 當(dāng)要進(jìn)行多條記錄的操作時(shí),我們就可以利用綁定進(jìn)行批處理。將槽更改如下: void?MainWindow::on_pushButton_clicked() { ? ??QSqlQuery?q; ? ??q.prepare("insert into student values (?, ?)"); ? ??QVariantList?ints; ? ??ints?<<?10?<<?11?<<?12?<<?13; ? ??q.addBindValue(ints); ? ??QVariantList?names; ? ??//?最后一個(gè)是空字符串,應(yīng)與前面的格式相同 names << "xiaoming" << "xiaoliang" << "xiaogang" << QVariant(QVariant::String); ? ??q.addBindValue(names); ? ??if?(!q.execBatch())?//進(jìn)行批處理,如果出錯(cuò)就輸出錯(cuò)誤 ? ?? ??qDebug()?<<?q.lastError(); ? ??//下面輸出整張表 ? ??QSqlQuery?query; ? ??query.exec("select * from student"); ? ??while(query.next()) ? ??{ ? ?? ??int?id?=?query.value(0).toInt(); ? ?? ??QString?name?=?query.value(1).toString(); ? ?? ??qDebug()?<<?id?<<?name; ? ??} } 然后需要在mainwindow.cpp上添加頭文件包含:#include?<QSqlError>。我們?cè)诔绦蛑欣昧斜泶鎯?chǔ)了同一屬性的多個(gè)值,然后進(jìn)行了值綁定。最后執(zhí)行execBatch()函數(shù)進(jìn)行批處理。注意程序中利用QVariant(QVariant::String)來(lái)輸入空值NULL,因?yàn)榍懊娑际?/span>QString類(lèi)型的,所以這里要使用QVariant::String?使格式一致化。 運(yùn)行程序,效果如下圖所示: 五、事務(wù)操作 事務(wù)可以保證一個(gè)復(fù)雜的操作的原子性,就是對(duì)于一個(gè)數(shù)據(jù)庫(kù)操作序列,這些操作要么全部做完,要么一條也不做,它是一個(gè)不可分割的工作單位。在Qt中,如果底層的數(shù)據(jù)庫(kù)引擎支持事務(wù),那么QSqlDriver::hasFeature(QSqlDriver::Transactions)會(huì)返回true。可以使用QSqlDatabase::transaction()來(lái)啟動(dòng)一個(gè)事務(wù),然后編寫(xiě)一些希望在事務(wù)中執(zhí)行的SQL語(yǔ)句,最后調(diào)用QSqlDatabase::commit()或者QSqlDatabase::rollback()。當(dāng)使用事務(wù)時(shí)必須在創(chuàng)建查詢(xún)以前就開(kāi)始事務(wù),例如: QSqlDatabase::database().transaction(); QSqlQuery?query; query.exec("SELECT id FROMemployee WHERE name = 'Torild Halvorsen'"); if?(query.next()) { ? ??int?employeeId = query.value(0).toInt(); ? ??query.exec("INSERT INTO project(id, name, ownerid) " ? ?? ?? ?? ?? ?"VALUES (201, 'ManhattanProject', " ? ?? ?? ?? ?? ?+?QString::number(employeeId) + ')'); } QSqlDatabase::database().commit(); 結(jié)語(yǔ) 對(duì)執(zhí)行SQL語(yǔ)句我們就介紹這么多,其實(shí)Qt中提供了更為簡(jiǎn)單的不需要SQL語(yǔ)句就可以操作數(shù)據(jù)庫(kù)的方法,我們?cè)谙乱还?jié)講述這些內(nèi)容。 涉及到的源碼:??myquery01.zip???myquery02.zip?? |
總結(jié)
以上是生活随笔為你收集整理的[Qt教程] 第23篇 数据库(三)利用QSqlQuery类执行SQL语句的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [Qt教程] 第22篇 数据库(二)编译
- 下一篇: [Qt教程] 第26篇 数据库(六)SQ