一文教你Qt如何操作SQLite數(shù)據(jù)庫(kù)
項(xiàng)目中通常需要采用各種數(shù)據(jù)庫(kù)(如 Qracle、SQL Server、MySQL等)來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)的存儲(chǔ)、查詢(xún)等功能。下面講解如何在 Qt 中操作 SQlite 數(shù)據(jù)庫(kù)。
1、SQLite 介紹
Sqlite 數(shù)據(jù)庫(kù)作為 Qt 項(xiàng)目開(kāi)發(fā)中經(jīng)常使用的一個(gè)輕量級(jí)的數(shù)據(jù)庫(kù),可以說(shuō)是兼容性相對(duì)比較好的數(shù)據(jù)庫(kù)之一(Sqlite就像Qt的親兒子,如同微軟兼容Access數(shù)據(jù)庫(kù)一樣)。Qt5 以上版本可以直接使用(Qt自帶驅(qū)動(dòng)),是一個(gè)輕量級(jí)的數(shù)據(jù)庫(kù),概況起來(lái)具有以下優(yōu)點(diǎn):
- SQLite 的設(shè)計(jì)目的是嵌入式 SQL 數(shù)據(jù)庫(kù)引擎,它基于純C語(yǔ)言代碼,已經(jīng)應(yīng)用于非常廣泛的領(lǐng)域內(nèi)。
- SQLite 在需要長(zhǎng)時(shí)間存儲(chǔ)時(shí)可以直接讀取硬盤(pán)上的數(shù)據(jù)文件(.db),在無(wú)須長(zhǎng)時(shí)間存儲(chǔ)時(shí)也可以將整個(gè)數(shù)據(jù)庫(kù)置于內(nèi)存中,兩者均不需要額外的服務(wù)器端進(jìn)程,即 SQLite 是無(wú)須獨(dú)立運(yùn)行的數(shù)據(jù)庫(kù)引擎。
- 源代碼開(kāi)源,你可以用于任何用途,包括出售它。
- 零配置 – 無(wú)需安裝和管理配置。
- 不需要配置,不需要安裝,也不需要管理員。
- 同一個(gè)數(shù)據(jù)文件可以在不同機(jī)器上使用,可以在不同字節(jié)序的機(jī)器間自由共享。
- 支持多種開(kāi)發(fā)語(yǔ)言,C, C++, PHP, Perl, Java, C#,Python, Ruby等。
2、用法
2.1、準(zhǔn)備
1、引入SQL模塊
在Qt項(xiàng)目文件(.pro文件)中,加入SQL模塊:
QT += sql
2、引用頭文件
在需要使用SQL的類(lèi)定義中,引用相關(guān)頭文件。例如:
#include <QSqlDatabase> #include <QSqlError> #include <QSqlQuery>
2.2、使用
1、建立數(shù)據(jù)庫(kù)
QSqlDatabase database;
if (QSqlDatabase::contains("qt_sql_default_connection"))
{
database = QSqlDatabase::database("qt_sql_default_connection");
}
else
{
// 建立和SQlite數(shù)據(jù)庫(kù)的連接
database = QSqlDatabase::addDatabase("QSQLITE");
// 設(shè)置數(shù)據(jù)庫(kù)文件的名字
database.setDatabaseName("MyDataBase.db");
}
第一行中,建立了一個(gè) QSqlDatabase 對(duì)象,后續(xù)的操作要使用這個(gè)對(duì)象。
if 語(yǔ)句用來(lái)檢查指定的連接(connection)是否存在。這里指定的連接名稱(chēng)(connection name)是qt_sql_default_connection,這是 Qt 默認(rèn)連接名稱(chēng)。實(shí)際使用時(shí),這個(gè)名稱(chēng)可以任意取。如果判斷此連接已經(jīng)存在,那么 QSqlDatabase::contains() 函數(shù)返回 true。此時(shí),進(jìn)入第一個(gè)分支,QSqlDatabase::database() 返回這個(gè)連接。
如果這個(gè)連接不存在,則進(jìn)入else分支,需要?jiǎng)?chuàng)建連接,并添加數(shù)據(jù)庫(kù)。在else分支第一行,addDatabase()的參數(shù)QSQLITE是SQLite對(duì)應(yīng)的驅(qū)動(dòng)名,不能改。而且需要注意的是,addDatabase()的第二個(gè)參數(shù)被省略了,第二個(gè)參數(shù)的默認(rèn)參數(shù)就是上面提到的Qt默認(rèn)連接名稱(chēng) qt_sql_default_connection。如果需要使用自定義的連接名稱(chēng)(如果程序需要處理多個(gè)數(shù)據(jù)庫(kù)文件的話(huà)就會(huì)這樣),則應(yīng)該加入第二個(gè)參數(shù),例如:
database = QSqlDatabase::addDatabase("QSQLITE", "my_sql_connection);
這個(gè)時(shí)候,如果在另一個(gè)地方需要判斷my_sql_connection連接是否存在,就應(yīng)該使用 if (QSqlDatabase::contains("my_sql_connection"))。
else 分支第二行中,setDatabaseName() 的參數(shù)是數(shù)據(jù)庫(kù)文件名。如果這個(gè)數(shù)據(jù)庫(kù)不存在,則會(huì)在后續(xù)操作時(shí)自動(dòng)創(chuàng)建;如果已經(jīng)存在,則后續(xù)的操作會(huì)在已有的數(shù)據(jù)庫(kù)上進(jìn)行。
2、打開(kāi)數(shù)據(jù)庫(kù)
使用 open() 打開(kāi)數(shù)據(jù)庫(kù),并判斷是否成功。注意,在第一步檢查連接是否存在時(shí),如果連接存在,則在返回這個(gè)連接的時(shí)候,會(huì)默認(rèn)將數(shù)據(jù)庫(kù)打開(kāi)。
if (!database.open())
{
qDebug() << "Error: Failed to connect database." << database.lastError();
}
else
{
// do something
}
如果打開(kāi)數(shù)據(jù)庫(kù)成功,則進(jìn)入else分支。對(duì)數(shù)據(jù)庫(kù)的操作都需要在else分支中進(jìn)行。
3、關(guān)閉數(shù)據(jù)庫(kù)
數(shù)據(jù)庫(kù)操作完成后,最好關(guān)閉。
database.close();
4、操作數(shù)據(jù)庫(kù)
對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作需要用到 QSqlQuery 類(lèi),操作前必須定義一個(gè)對(duì)象。下面舉例說(shuō)明操作方法。操作需要使用 SQL 語(yǔ)句,本文中的幾個(gè)例子會(huì)使用幾個(gè)常用的語(yǔ)句,關(guān)于 SQL 語(yǔ)句的具體信息可以參考我的另一篇博客:[SQL必知必會(huì)] 讀書(shū)筆記 。
例1:創(chuàng)建表格
創(chuàng)建一個(gè)名為student的表格,表格包含三列,第一列是id,第二列是名字,第三列是年齡。
// 用于執(zhí)行sql語(yǔ)句的對(duì)象
QSqlQuery sqlQuery;
// 構(gòu)建創(chuàng)建數(shù)據(jù)庫(kù)的sql語(yǔ)句字符串
QString createSql = QString("CREATE TABLE student (\
id INT PRIMARY KEY NOT NULL,\
name TEXT NOT NULL,\
age INT NOT NULL)");
sqlQuery.prepare(createSql);
// 執(zhí)行sql語(yǔ)句
if(!sqlQuery.exec())
{
qDebug() << "Error: Fail to create table. " << sqlQuery.lastError();
}
else
{ qDebug() << "Table created!";
}第一行定義一個(gè) QSqlQuery 對(duì)象。
第二行是一個(gè) QString,其中的內(nèi)容是 SQLite 語(yǔ)句。對(duì)數(shù)據(jù)庫(kù)的操作,都是用 SQLite 的語(yǔ)句完成的,把這些指令以 QString 類(lèi)型,通過(guò) prepare 函數(shù),保存在 QSqlQuery 對(duì)象中。也可將指令,以 QString 形式直接寫(xiě)在 exec() 函數(shù)的參數(shù)中,例如:
sql_query.exec("CREATE TABLE student (ID INT PRIMARY KEY NOT NULL, ...)");
如果 sql_query.exec() 執(zhí)行成功,則創(chuàng)建表格成功。
例2:插入單行數(shù)據(jù)
在剛才創(chuàng)建的表格中,插入單行數(shù)據(jù)。
// 方法一:使用 bindValue 函數(shù)插入單行數(shù)據(jù)
QSqlQuery sqlQuery;
sqlQuery.prepare("INSERT INTO student VALUES(:id,:name,:age)");
sqlQuery.bindValue(":id", max_id + 1);
sqlQuery.bindValue(":name", "Wang");
sqlQuery.bindValue(":age", 25);
if(!sqlQuery.exec())
{
qDebug() << "Error: Fail to insert data. " << sqlQuery.lastError();
}
else
{
// do something
}
// 方法二:使用 addBindValue 函數(shù)插入單行數(shù)據(jù)
QSqlQuery sqlQuery;
sqlQuery.prepare("INSERT INTO student VALUES(?, ?, ?)");
sqlQuery.addBindValue(max_id + 1);
sqlQuery.addBindValue("Wang");
sqlQuery.addBindValue(25);
if(!sqlQuery.exec())
{
qDebug() << "Error: Fail to insert data. " << sqlQuery.lastError();
}
else
{
// do something
}
// 方法三:直接寫(xiě)出完整語(yǔ)句
if(!sql_query.exec("INSERT INTO student VALUES(3, \"Li\", 23)"))
{
qDebug() << "Error: Fail to insert data. " << sqlQuery.lastError();
}
else
{
// do something
}例3:查詢(xún)?nèi)繑?shù)據(jù)
QSqlQuery sqlQuery;
sqlQuery.exec("SELECT * FROM student");
if(!sqlQuery.exec())
{
qDebug() << "Error: Fail to query table. " << sqlQuery.lastError();
}
else
{
while(sqlQuery.next())
{
int id = sqlQuery.value(0).toInt();
QString name = sqlQuery.value(1).toString();
int age = sqlQuery.value(2).toInt();
qDebug()<<QString("id:%1 name:%2 age:%3").arg(id).arg(name).arg(age);
}
}例4:更新數(shù)據(jù)(修改數(shù)據(jù))
QSqlQuery sqlQuery;
sqlQuery.prepare("UPDATE student SET name=?,age=? WHERE id=?");
sqlQuery.addBindValue(name);
sqlQuery.addBindValue(age);
sqlQuery.addBindValue(id);
if(!sqlQuery.exec())
{
qDebug() << sqlQuery.lastError();
}
else
{
qDebug() << "updated data success!";
}
3、完整示例程序
上面只是列舉了幾個(gè)常用的SQL語(yǔ)句例子,下面貼出一個(gè)完整示例程序:
SqliteOperator.h
#ifndef SQLITEOPERATOR_H
#define SQLITEOPERATOR_H
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
typedef struct
{
int id;
QString name;
int age;
}w2dba;
class SqliteOperator
{
public:
SqliteOperator();
// 打開(kāi)數(shù)據(jù)庫(kù)
bool openDb(void);
// 創(chuàng)建數(shù)據(jù)表
void createTable(void);
// 判斷數(shù)據(jù)表是否存在
bool isTableExist(QString& tableName);
// 查詢(xún)?nèi)繑?shù)據(jù)
void queryTable();
// 插入數(shù)據(jù)
void singleInsertData(w2dba &singleData); // 插入單條數(shù)據(jù)
void moreInsertData(QList<w2dba> &moreData); // 插入多條數(shù)據(jù)
// 修改數(shù)據(jù)
void modifyData(int id, QString name, int age);
// 刪除數(shù)據(jù)
void deleteData(int id);
//刪除數(shù)據(jù)表
void deleteTable(QString& tableName);
// 關(guān)閉數(shù)據(jù)庫(kù)
void closeDb(void);
private:
QSqlDatabase database;// 用于建立和數(shù)據(jù)庫(kù)的連接
};
#endif // SQLITEOPERATOR_HSqliteOperator.cpp
#include "sqliteoperator.h"
// 構(gòu)造函數(shù)中初始化數(shù)據(jù)庫(kù)對(duì)象,并建立數(shù)據(jù)庫(kù)
SqliteOperator::SqliteOperator()
{
if (QSqlDatabase::contains("qt_sql_default_connection"))
{
database = QSqlDatabase::database("qt_sql_default_connection");
}
else
{
// 建立和SQlite數(shù)據(jù)庫(kù)的連接
database = QSqlDatabase::addDatabase("QSQLITE");
// 設(shè)置數(shù)據(jù)庫(kù)文件的名字
database.setDatabaseName("MyDataBase.db");
}
}
// 打開(kāi)數(shù)據(jù)庫(kù)
bool SqliteOperator::openDb()
{
if (!database.open())
{
qDebug() << "Error: Failed to connect database." << database.lastError();
}
else
{
// do something
}
return true;
}
// 創(chuàng)建數(shù)據(jù)表
void SqliteOperator::createTable()
{
// 用于執(zhí)行sql語(yǔ)句的對(duì)象
QSqlQuery sqlQuery;
// 構(gòu)建創(chuàng)建數(shù)據(jù)庫(kù)的sql語(yǔ)句字符串
QString createSql = QString("CREATE TABLE student (\
id INT PRIMARY KEY NOT NULL,\
name TEXT NOT NULL,\
age INT NOT NULL)");
sqlQuery.prepare(createSql);
// 執(zhí)行sql語(yǔ)句
if(!sqlQuery.exec())
{
qDebug() << "Error: Fail to create table. " << sqlQuery.lastError();
}
else
{
qDebug() << "Table created!";
}
}
// 判斷數(shù)據(jù)庫(kù)中某個(gè)數(shù)據(jù)表是否存在
bool SqliteOperator::isTableExist(QString& tableName)
{
QSqlDatabase database = QSqlDatabase::database();
if(database.tables().contains(tableName))
{
return true;
}
return false;
}
// 查詢(xún)?nèi)繑?shù)據(jù)
void SqliteOperator::queryTable()
{
QSqlQuery sqlQuery;
sqlQuery.exec("SELECT * FROM student");
if(!sqlQuery.exec())
{
qDebug() << "Error: Fail to query table. " << sqlQuery.lastError();
}
else
{
while(sqlQuery.next())
{
int id = sqlQuery.value(0).toInt();
QString name = sqlQuery.value(1).toString();
int age = sqlQuery.value(2).toInt();
qDebug()<<QString("id:%1 name:%2 age:%3").arg(id).arg(name).arg(age);
}
}
}
// 插入單條數(shù)據(jù)
void SqliteOperator::singleInsertData(w2dba &singledb)
{
QSqlQuery sqlQuery;
sqlQuery.prepare("INSERT INTO student VALUES(:id,:name,:age)");
sqlQuery.bindValue(":id", singledb.id);
sqlQuery.bindValue(":name", singledb.name);
sqlQuery.bindValue(":age", singledb.age);
if(!sqlQuery.exec())
{
qDebug() << "Error: Fail to insert data. " << sqlQuery.lastError();
}
else
{
// do something
}
}
// 插入多條數(shù)據(jù)
void SqliteOperator::moreInsertData(QList<w2dba>& moredb)
{
// 進(jìn)行多個(gè)數(shù)據(jù)的插入時(shí),可以利用綁定進(jìn)行批處理
QSqlQuery sqlQuery;
sqlQuery.prepare("INSERT INTO student VALUES(?,?,?)");
QVariantList idList,nameList,ageList;
for(int i=0; i< moredb.size(); i++)
{
idList << moredb.at(i).id;
nameList << moredb.at(i).name;
ageList << moredb.at(i).age;
}
sqlQuery.addBindValue(idList);
sqlQuery.addBindValue(nameList);
sqlQuery.addBindValue(ageList);
if (!sqlQuery.execBatch()) // 進(jìn)行批處理,如果出錯(cuò)就輸出錯(cuò)誤
{
qDebug() << sqlQuery.lastError();
}
}
// 修改數(shù)據(jù)
void SqliteOperator::modifyData(int id, QString name, int age)
{
QSqlQuery sqlQuery;
sqlQuery.prepare("UPDATE student SET name=?,age=? WHERE id=?");
sqlQuery.addBindValue(name);
sqlQuery.addBindValue(age);
sqlQuery.addBindValue(id);
if(!sqlQuery.exec())
{
qDebug() << sqlQuery.lastError();
}
else
{
qDebug() << "updated data success!";
}
}
// 刪除數(shù)據(jù)
void SqliteOperator::deleteData(int id)
{
QSqlQuery sqlQuery;
sqlQuery.exec(QString("DELETE FROM student WHERE id = %1").arg(id));
if(!sqlQuery.exec())
{
qDebug()<<sqlQuery.lastError();
}
else
{
qDebug()<<"deleted data success!";
}
}
//刪除數(shù)據(jù)表
void SqliteOperator::deleteTable(QString& tableName)
{
QSqlQuery sqlQuery;
sqlQuery.exec(QString("DROP TABLE %1").arg(tableName));
if(sqlQuery.exec())
{
qDebug() << sqlQuery.lastError();
}
else
{
qDebug() << "deleted table success";
}
}
void SqliteOperator::closeDb(void)
{
database.close();
}main.cpp
#include <QCoreApplication>
#include "sqliteoperator.h"
#include <QString>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//創(chuàng)建并打開(kāi)SQLite數(shù)據(jù)庫(kù)
SqliteOperator sqlTest;
sqlTest.openDb();
// 創(chuàng)建數(shù)據(jù)表
sqlTest.createTable();
// 判斷數(shù)據(jù)表是否存在
QString str1 = QString("student");
qDebug() << "isTabelExist:" <<sqlTest.isTableExist(str1);
// 插入單條數(shù)據(jù)
w2dba w2dbaTest1 = {1, "zhangSan", 24};
w2dba w2dbaTest2 = {2, "lisi", 28};
sqlTest.singleInsertData(w2dbaTest1);
sqlTest.singleInsertData(w2dbaTest2);
// 插入多條數(shù)據(jù)
QList<w2dba> list;
w2dba w2dbaTest3 = {3, "liwu", 26};
w2dba w2dbaTest4 = {4, "niuer", 27};
list.append(w2dbaTest3);
list.append(w2dbaTest4);
sqlTest.moreInsertData(list);
// 查詢(xún)?nèi)繑?shù)據(jù)
sqlTest.queryTable();
qDebug() << endl;
// 修改數(shù)據(jù)
sqlTest.modifyData(2, "modify", 10);
// 查詢(xún)?nèi)繑?shù)據(jù)
sqlTest.queryTable();
qDebug() << endl;
// 刪除數(shù)據(jù)
sqlTest.deleteData(2);
// 查詢(xún)?nèi)繑?shù)據(jù)
sqlTest.queryTable();
qDebug() << endl;
// 刪除數(shù)據(jù)表
QString str2 = QString("student");
sqlTest.deleteTable(str2);
//關(guān)閉數(shù)據(jù)庫(kù)
sqlTest.closeDb();
return a.exec();
}運(yùn)行結(jié)果如下:
Table created!
isTabelExist: true
"id:1 name:zhangSan age:24"
"id:2 name:lisi age:28"
"id:3 name:liwu age:26"
"id:4 name:niuer age:27"
updated data success!
"id:1 name:zhangSan age:24"
"id:2 name:modify age:10"
"id:3 name:liwu age:26"
"id:4 name:niuer age:27"
deleted data success!
"id:1 name:zhangSan age:24"
"id:3 name:liwu age:26"
"id:4 name:niuer age:27"
deleted table success
以上就是一文教你Qt如何操作SQLite數(shù)據(jù)庫(kù)的詳細(xì)內(nèi)容,更多關(guān)于Qt操作SQLite數(shù)據(jù)庫(kù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)中約瑟夫環(huán)問(wèn)題探究
這篇文章主要介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)中約瑟夫環(huán)問(wèn)題,總的來(lái)說(shuō)這并不是一道難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達(dá)的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過(guò)程。希望通過(guò)這道題能給你帶來(lái)一種解題優(yōu)化的思路2023-01-01
Java?C++題解leetcode1598文件夾操作日志搜集器
這篇文章主要為大家介紹了Java?C++題解leetcode1598文件夾操作日志搜集器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Qt中網(wǎng)絡(luò)編程的實(shí)現(xiàn)
本文主要介紹了Qt中網(wǎng)絡(luò)編程的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-02-02
深入剖析Android中init進(jìn)程實(shí)現(xiàn)的C語(yǔ)言源碼
這篇文章主要介紹了Android中init進(jìn)程實(shí)現(xiàn)的C語(yǔ)言源碼,init屬性服務(wù)在安卓中屬于系統(tǒng)的底層Linux服務(wù),需要的朋友可以參考下2015-07-07

