Qt学习笔记之SQLITE数据库
1. SQLite數(shù)據(jù)庫(kù)介紹
SQLite,是一款輕型的數(shù)據(jù)庫(kù),是遵守ACID的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),它包含在一個(gè)相對(duì)小的C庫(kù)中。它是D.RichardHipp建立的公有領(lǐng)域項(xiàng)目。它的設(shè)計(jì)目標(biāo)是嵌入式的,而且已經(jīng)在很多嵌入式產(chǎn)品中使用了它,它占用資源非常的低,在嵌入式設(shè)備中,可能只需要幾百K的內(nèi)存就夠了。它能夠支持Windows/Linux/Unix等等主流的操作系統(tǒng),同時(shí)能夠跟很多程序語(yǔ)言相結(jié)合,比如 Tcl、C#、PHP、Java等,還有ODBC接口,同樣比起Mysql、PostgreSQL這兩款開源的世界著名數(shù)據(jù)庫(kù)管理系統(tǒng)來講,它的處理速度比他們都快。SQLite第一個(gè)Alpha版本誕生于2000年5月。 至2019年已經(jīng)有19個(gè)年頭,SQLite也迎來了一個(gè)版本 SQLite 3已經(jīng)發(fā)布。
Qt提供了一種進(jìn)程內(nèi)數(shù)據(jù)庫(kù)——SQLite,它小巧靈活,無須額外安裝配置且支持大部分ANSI SQL92標(biāo)準(zhǔn),是一個(gè)輕量級(jí)的數(shù)據(jù)庫(kù),概括起來它具有以下優(yōu)點(diǎn):
(1)SQlite的設(shè)計(jì)目的是嵌入式SQL數(shù)據(jù)庫(kù)引擎,它基于純C語(yǔ)言代碼,應(yīng)用非常廣泛。
(2)SQlite在需要持久存儲(chǔ)時(shí),可以直接讀寫硬盤上的數(shù)據(jù)文件,在無須持久存儲(chǔ)時(shí),也可以將整個(gè)數(shù)據(jù)庫(kù)置于內(nèi)存中,兩者均不需要額外的server服務(wù)端進(jìn)程,即SQlite是無須獨(dú)立運(yùn)行的數(shù)據(jù)庫(kù)引擎。
(3)開放源代碼,整個(gè)代碼少于三萬行,有良好的注釋和90%以上的測(cè)試覆蓋率。
(4)少于250K的內(nèi)存占用(gcc編譯下)。
(5)支持視圖、觸發(fā)器、事務(wù),支持嵌套SQL功能。
(6)提供虛擬機(jī)用于處理SQL語(yǔ)句。
(7)不需要配置,不需要安裝,也不需要管理員。
(8)支持大部分ANSI SQL92標(biāo)準(zhǔn)。
(9)大部分應(yīng)用的速度比目前常見的客戶端/服務(wù)器結(jié)構(gòu)的數(shù)據(jù)庫(kù)快。
(10)編程接口簡(jiǎn)單易用。
在持久存儲(chǔ)的情況下,一個(gè)完整的數(shù)據(jù)庫(kù)就對(duì)應(yīng)磁盤上面的一個(gè)文件,它是一種具備了基本數(shù)據(jù)庫(kù)特性的數(shù)據(jù)文件,同一個(gè)數(shù)據(jù)文件可以在不同機(jī)器上面使用,可以在不同字節(jié)序的機(jī)器間自由共享,最大支持2TB數(shù)據(jù)容量,而且性能僅受限于系統(tǒng)的可用內(nèi)存,沒有其他依賴,可以應(yīng)用于多種操作系統(tǒng)平臺(tái)。
SQLite可視化管理工具(SQLite?Expert Pro)
2. Qt操作SQLite數(shù)據(jù)庫(kù)
2.1 創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)
?QSqlDatabase類提供了一個(gè)接口,用于通過連接訪問數(shù)據(jù)。
//! 添加數(shù)據(jù)庫(kù)驅(qū)動(dòng)QSqlDatabase mySqlLiteDB = QSqlDatabase::addDatabase("QSQLITE");//! 設(shè)置數(shù)據(jù)庫(kù)名稱mySqlLiteDB.setDatabaseName("E:/work/qe/mytest1/database.db");//! 打開數(shù)據(jù)庫(kù)if(!mySqlLiteDB.open())return false;2.2 創(chuàng)建一個(gè)表
QSqlQuery類可以使用SQL語(yǔ)句來實(shí)現(xiàn)與數(shù)據(jù)庫(kù)交互。
//! 以下執(zhí)行相關(guān)sql語(yǔ)句QSqlQuery mySqlQuery;//! 清空student表mySqlQuery.exec("drop table student");//! 新建student表,id設(shè)置為主鍵,還有一個(gè)name項(xiàng)mySqlQuery.exec("create table student (id int primary key, name vchar,course int)");主鍵:表中經(jīng)常有一個(gè)列或多列的組合,其值能唯一地標(biāo)識(shí)表中的每一行。這樣的一列或多列稱為表的主鍵,通過它可強(qiáng)制表的實(shí)體完整性。當(dāng)創(chuàng)建或更改表時(shí)可通過定義 PRIMARY KEY 約束來創(chuàng)建主鍵。一個(gè)表只能有一個(gè) PRIMARY KEY 約束,而且 PRIMARY KEY 約束中的列不能接受空值。由于 PRIMARY KEY 約束確保唯一數(shù)據(jù),所以經(jīng)常用來定義標(biāo)識(shí)列。
作用:
1)保證實(shí)體的完整性;
2)加快數(shù)據(jù)庫(kù)的操作速度
3) 在表中添加新記錄時(shí),DBMS會(huì)自動(dòng)檢查新記錄的主鍵值,不允許該值與其他記錄的主鍵值重復(fù)。
4) DBMS自動(dòng)按主鍵值的順序顯示表中的記錄。如果沒有定義主鍵,則按輸入記錄的順序顯示表中的記錄。
2.3 插入數(shù)據(jù)?
2.3.1 批量插入
可以用prepare()來綁值,然后再通過bindValue()向綁值加入數(shù)據(jù)。
//!批量導(dǎo)入QStringList strListStdName;strListStdName<<"wang bin"<<"xiao yu"<<"ye mei";QStringList strListStdCourse;strListStdCourse<<"Math"<<"English"<<"Computer";mySqlQuery.prepare("INSERT INTO student (id,name, course) ""VALUES (:id,:name, :course)");for (int i = 0; i < strListStdName.size(); i++){mySqlQuery.bindValue(":id",i); //! 加入主鍵mySqlQuery.bindValue(":name", strListStdName[i]); //! 向綁定值里加入名字mySqlQuery.bindValue(":course", strListStdCourse[i]); //! 課程mySqlQuery.exec(); //! 加入庫(kù)中}//! 向表中插入1條數(shù)據(jù)mySqlQuery.bindValue(0,3);mySqlQuery.bindValue(1,"wang han");mySqlQuery.bindValue(2,"Chinese");mySqlQuery.exec();?這里在student表的最后又添加了一條記錄。然后我們先使用了prepare()函數(shù),在其中利用了“:id”和“:name”來代替具體的數(shù)據(jù),而后又利用bindValue()函數(shù)給id和name兩個(gè)屬性賦值,這稱為綁定操作。其中編號(hào)0和1分別代表“:id”和“:name”,就是說按照prepare()函數(shù)中出現(xiàn)的屬性從左到右編號(hào),最左邊是0 。
特別注意,在最后一定要執(zhí)行exec()函數(shù),所做的操作才能被真正執(zhí)行。運(yùn)行程序,點(diǎn)擊查詢按鈕,可以看到前面添加的記錄的信息。這里的“:id”和“:name”,叫做占位符,這是ODBC數(shù)據(jù)庫(kù)的表示方法,還有一種Oracle的表示方法就是全部用“?”號(hào)。例如:
query.prepare("insert into student(id, name) ""values (?, ?)"); query.bindValue(0, 5); query.bindValue(1, "sixth"); query.exec();也可以利用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();以上各種形式的表示方式效果是一樣的。
2.3.2 用insert into語(yǔ)句
//! 單條導(dǎo)入mySqlQuery.exec("insert into student values(3,'wang han','Chinese')");2.4? 查詢表內(nèi)容?
?可以用select語(yǔ)句查詢表內(nèi)容
//! 查找表中id >=1 的記錄的id項(xiàng)和name項(xiàng)的值mySqlQuery.exec("select * from student where id >= 1");//! query.next()指向查找到的第一條記錄,然后每次后移一條記錄QSqlRecord mySqlRec = mySqlQuery.record();while(mySqlQuery.next()){//! 獲取query所指向的記錄在結(jié)果集中的編號(hào)int nRowNum = mySqlQuery.at();//! 獲取每條記錄中屬性(即列)的個(gè)數(shù)int nColumnNum = mySqlQuery.record().count();//! 獲取"name"屬性所在列的編號(hào),列從左向右編號(hào),最左邊的編號(hào)為0int nFieldNo = mySqlQuery.record().indexOf("name");nFieldNo = mySqlRec.indexOf("course");//! 獲取id屬性的值,并轉(zhuǎn)換為int型int stud_id = mySqlQuery.value(0).toInt();//! 獲取name屬性的值QString stud_name = mySqlQuery.value(1).toString();//! 獲取course屬性的值QString stud_course = mySqlQuery.value(2).toString();//! 輸出結(jié)果qDebug() << nRowNum << nColumnNum << nFieldNo << stud_id << stud_name << stud_course;}//! 定位到結(jié)果集中編號(hào)為2的記錄,即第三條記錄,因?yàn)榈谝粭l記錄的編號(hào)為0qDebug() << "exec seek(2) :";if(mySqlQuery.seek(2)){qDebug() << "rowNum is : " << mySqlQuery.at()<< " id is : " << mySqlQuery.value(0).toInt()<< " name is : " << mySqlQuery.value(1).toString();}//! 定位到結(jié)果集中最后一條記錄qDebug() << "exec last() :";if(mySqlQuery.last()){qDebug() << "rowNum is : " << mySqlQuery.at()<< " id is : " << mySqlQuery.value(0).toInt()<< " name is : " << mySqlQuery.value(1).toString();}輸出結(jié)果?
在前面的程序中,我們使用
mySqlQuery.exec("select * from student where id >= 1");查詢出表中所有的內(nèi)容。其中的SQL語(yǔ)句“select * from student”中“*”號(hào)表明查詢表中記錄的所有屬性。而當(dāng)mySqlQuery.exec("select * from student");這條語(yǔ)句執(zhí)行完后,我們便獲得了相應(yīng)的執(zhí)行結(jié)果,因?yàn)楂@得的結(jié)果可能不止一條記錄,所以稱之為結(jié)果集。
結(jié)果集其實(shí)就是查詢到的所有記錄的集合,在QSqlQuery類中提供了多個(gè)函數(shù)來操作這個(gè)集合,需要注意這個(gè)集合中的記錄是從0開始編號(hào)的。最常用的操作有:
- seek(int n) :query指向結(jié)果集的第n條記錄;
- first() :query指向結(jié)果集的第一條記錄;
- last() :query指向結(jié)果集的最后一條記錄;
- next() :query指向下一條記錄,每執(zhí)行一次該函數(shù),便指向相鄰的下一條記錄;
- previous() :query指向上一條記錄,每執(zhí)行一次該函數(shù),便指向相鄰的上一條記錄;
- record() :獲得現(xiàn)在指向的記錄;
- value(int n) :獲得屬性的值。其中n表示你查詢的第n個(gè)屬性,比方上面我們使用“select * from student”就相當(dāng)于“select id, name from student”,那么value(0)返回id屬性的值,value(1)返回name屬性的值。該函數(shù)返回QVariant類型的數(shù)據(jù),關(guān)于該類型與其他類型的對(duì)應(yīng)關(guān)系,可以在幫助中查看QVariant。
- at() :獲得現(xiàn)在query指向的記錄在結(jié)果集中的編號(hào)。
需要特別注意,剛執(zhí)行完mySqlQuery.exec("select *from student");這行代碼時(shí),mySqlQuery是指向結(jié)果集以外的,我們可以利用mySqlQuery.next()使得mySqlQuery指向結(jié)果集的第一條記錄。當(dāng)然我們也可以利用seek(0)函數(shù)或者first()函數(shù)使mySqlQuery指向結(jié)果集的第一條記錄。但是為了節(jié)省內(nèi)存開銷,推薦的方法是,在mySqlQuery.exec("select * from student");這行代碼前加上mySqlQuery.setForwardOnly(true);這條代碼,此后只能使用next()和seek()函數(shù)。
2.5 刪除表內(nèi)容?
2.5.1 DROP 語(yǔ)句? ? ? ??
用來刪除整表,并且連表結(jié)構(gòu)也會(huì)刪除,刪除后則只能使用CREATE TABLE來重新創(chuàng)建表
//! 刪除表內(nèi)容mySqlQuery.exec("drop table student");2.5.2 TRUNCATE語(yǔ)句
?在SQLite中沒有該語(yǔ)句,在MySQL中有該語(yǔ)句,用來清楚表內(nèi)數(shù)據(jù),但是表結(jié)構(gòu)不會(huì)刪除.
2.5.3 DELETE語(yǔ)句? ? ??
刪除部分記錄,并且表結(jié)構(gòu)不會(huì)刪除,刪除的速度比上面兩個(gè)語(yǔ)句慢,可以配合WHERE來刪除指定的某行
1) 刪除整個(gè)表?
mySqlQuery.exec("delete table student");?
?2) 刪除某行
mySqlQuery.exec("delete from student where id = 1");?
2.6 修改表內(nèi)容?
2.6.1 update
UPDATE 語(yǔ)句用于更新表中已存在的記錄。
SQL UPDATE 語(yǔ)法
UPDATE?table_name
SET?column1=value1,column2=value2,...
WHERE?some_column=some_value;
2.6.2 alter語(yǔ)句?
1) 如需在表中添加列,請(qǐng)使用下面的語(yǔ)法:
ALTER TABLE table_name ADD column_name datatype
mySqlQuery.exec("alter table student add score int");2)? 如需刪除表中的列,請(qǐng)使用下面的語(yǔ)法(請(qǐng)注意,某些數(shù)據(jù)庫(kù)系統(tǒng)不允許這種在數(shù)據(jù)庫(kù)表中刪除列的方式,該行在SQlite中不能用,SQlite不支持drop):
ALTER TABLE table_name DROP COLUMN column_name
3) 要改變表中列的數(shù)據(jù)類型,請(qǐng)使用下面的語(yǔ)法:
ALTER TABLE table_name ALTER COLUMN column_name datatype
?參考資料:
1.?SQlite在已創(chuàng)建的表中刪除一列
2.42.QT-QSqlQuery類操作SQLite數(shù)據(jù)庫(kù)(創(chuàng)建、查詢、刪除、修改)詳解
?
?
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的Qt学习笔记之SQLITE数据库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt学习笔记之数据库
- 下一篇: Qt操作SQLite数据库练习(2020