亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Qt操作SQLite數(shù)據(jù)庫(kù)的教程詳解

 更新時(shí)間:2022年12月08日 08:51:26   作者:音視頻開發(fā)老舅  
SQLite是一款開源、輕量級(jí)、跨平臺(tái)的數(shù)據(jù)庫(kù),無(wú)需server,無(wú)需安裝和管理配置。它的設(shè)計(jì)目標(biāo)是嵌入式的,所以很適合小型應(yīng)用,也是Qt應(yīng)用開發(fā)種常用的一種數(shù)據(jù)庫(kù)。本文為大家介紹了Qt操作SQLite數(shù)據(jù)庫(kù)的示例,希望對(duì)大家有所幫助

0.前言

SQLite是一款開源、輕量級(jí)、跨平臺(tái)的數(shù)據(jù)庫(kù),無(wú)需server,無(wú)需安裝和管理配置。它的設(shè)計(jì)目標(biāo)是嵌入式的,所以很適合小型應(yīng)用,也是Qt應(yīng)用開發(fā)種常用的一種數(shù)據(jù)庫(kù)。

1.驅(qū)動(dòng)

Qt SQL模塊使用驅(qū)動(dòng)程序插件(plugins)與不同的數(shù)據(jù)庫(kù)API進(jìn)行通信。由于Qt的SQL模塊API與數(shù)據(jù)庫(kù)無(wú)關(guān),因此所有特定于數(shù)據(jù)庫(kù)的代碼都包含在這些驅(qū)動(dòng)程序中。Qt提供了幾個(gè)驅(qū)動(dòng)程序,也可以添加其他驅(qū)動(dòng)程序。提供驅(qū)動(dòng)程序源代碼,可用作編寫自己的驅(qū)動(dòng)程序的模型。

QtCreator在*.pro中引入sql模塊(QT+=sql),或是VS中在Qt VS Tool里勾選上sql模塊,就可以使用該模塊的接口了。

可以使用QSqlDatabase::drivers()獲取驅(qū)動(dòng)程序列表并打印,Qt5.9.7輸出如下:

其中,SQLite是一個(gè)進(jìn)程內(nèi)數(shù)據(jù)庫(kù),這意味著沒有必要擁有數(shù)據(jù)庫(kù)服務(wù)器。SQLite在單個(gè)文件上運(yùn)行,在打開連接時(shí)必須將其設(shè)置為數(shù)據(jù)庫(kù)名稱。如果該文件不存在,SQLite將嘗試創(chuàng)建它。。

2.初相遇

/*
 * ... ...
 * 我喜歡那樣的夢(mèng)
 * 在夢(mèng)里 一切都可以重新開始
 * 一切都可以慢慢解釋
 * 心里甚至還能感覺到所有被浪費(fèi)的時(shí)光
 * 竟然都能重回時(shí)的狂喜和感激
 * ... ...
 * 
 *                ----席慕容《初相遇》
 */
 
 
#include <QSqlDatabase>
#include <QDebug>
 
void initDb()
{   
    //qDebug()<<QSqlDatabase::drivers();//打印驅(qū)動(dòng)列表
    QSqlDatabase db;
    //檢測(cè)已連接的方式 - 默認(rèn)連接名
    //QSqlDatabase::contains(QSqlDatabase::defaultConnection)
    if(QSqlDatabase::contains("qt_sql_default_connection"))
        db = QSqlDatabase::database("qt_sql_default_connection");
    else
        db = QSqlDatabase::addDatabase("QSQLITE");
    //檢測(cè)已連接的方式 - 自定義連接名
    /*if(QSqlDatabase::contains("mysql_connection"))
        db = QSqlDatabase::database("mysql_connection");
    else
        db = QSqlDatabase::addDatabase("QSQLITE","mysql_connection");*/
    //設(shè)置數(shù)據(jù)庫(kù)路徑,不存在則創(chuàng)建
    db.setDatabaseName("sqltest.db");
    //db.setUserName("gongjianbo");  //SQLite不需要用戶名和密碼
    //db.setPassword("qq654344883");
    
    //打開數(shù)據(jù)庫(kù)
    if(db.open()){
        qDebug()<<"open success";
        //關(guān)閉數(shù)據(jù)庫(kù)
        db.close();
    }
    
}

上面的代碼中,先是創(chuàng)建了一個(gè)QSqlDatabase對(duì)象,該類用于處理數(shù)據(jù)庫(kù)的連接。contains方法用于查看給定的連接名稱是否在連接列表中,database方法獲取數(shù)據(jù)庫(kù)連接,前提是已使用addDatabase添加數(shù)據(jù)庫(kù)連接。addDatabase聲明如下:

QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatin1String(defaultConnection)) [static]

第一個(gè)參數(shù)對(duì)應(yīng)驅(qū)動(dòng)名,第二個(gè)參數(shù)為連接名稱 ,如果不使用默認(rèn)連接名稱“qt_sql_default_connection”的話需要填寫該參數(shù)。

設(shè)置了驅(qū)動(dòng)及連接名稱后,就是設(shè)置數(shù)據(jù)庫(kù)文件的名稱/路徑,因?yàn)镾QLite不需要用戶名和密碼,接下來(lái)直接就可以通過open和close函數(shù)來(lái)打開關(guān)閉該數(shù)據(jù)庫(kù)了。

此外,如果需要在內(nèi)存中創(chuàng)建數(shù)據(jù)庫(kù),而不是指定一個(gè)文件,可以setDatabaseName(“:memory:”);

db.setDatabaseName(":memory:");

3.創(chuàng)建表

SQL語(yǔ)句執(zhí)行需要用到QSqlQuery類,文檔有云:

QSqlQuery封裝了在QSqlDatabase上執(zhí)行的SQL查詢中創(chuàng)建,導(dǎo)航和檢索數(shù)據(jù)所涉及的功能。它可以被用來(lái)執(zhí)行DML(數(shù)據(jù)操縱語(yǔ)言)語(yǔ)句,例如select、insert、update、delete,以及DDL(數(shù)據(jù)定義語(yǔ)言)語(yǔ)句,如create table,還可以用于執(zhí)行非標(biāo)準(zhǔn)SQL的特定于數(shù)據(jù)庫(kù)的命令。

成功執(zhí)行的SQL語(yǔ)句將查詢的狀態(tài)設(shè)置為活動(dòng)狀態(tài),以便isActive()返回true。否則,查詢的狀態(tài)將設(shè)置為非活動(dòng)狀態(tài)。在任何一種情況下,執(zhí)行新的SQL語(yǔ)句時(shí),查詢都位于無(wú)效記錄上。必須先將活動(dòng)查詢導(dǎo)航到有效記錄(以便isActive()返回true),然后才能檢索值。

#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
 
void createTable()
{
    //sql語(yǔ)句不熟悉的推薦《sql必知必會(huì)》,輕松入門
    //如果不存在則創(chuàng)建my_table表
    //id自增,name唯一
    const QString sql=R"(
                      CREATE TABLE IF NOT EXISTS  my_table (
                      id   INTEGER   PRIMARY KEY AUTOINCREMENT NOT NULL,
                      name CHAR (50) UNIQUE NOT NULL,
                      age  INTEGER
                      );)";
    //QSqlQuery構(gòu)造前,需要db已打開并連接
    //未指定db或者db無(wú)效時(shí)使用默認(rèn)連接進(jìn)行操作
    QSqlQuery query;
    
    if(query.exec(sql)){
        qDebug()<<"init table success";
    }else{
        //打印sql語(yǔ)句錯(cuò)誤信息
        qDebug()<<"init table error"<<query.lastError();
    }
}

代碼通過QSqlQuery的exec方法執(zhí)行SQL語(yǔ)句,創(chuàng)建了一個(gè)簡(jiǎn)單的數(shù)據(jù)表。exec執(zhí)行SQL語(yǔ)句成功返回true,否則返回false。

QSqlQuery的構(gòu)造函數(shù)可以指定QDatabase參數(shù),如果未指定db,或者db無(wú)效將使用默認(rèn)連接。

QSqlQuery::QSqlQuery(QSqlDatabase db);

要注意的是,對(duì)于SQLite,exec方法一次只能執(zhí)行一個(gè)語(yǔ)句。

4.執(zhí)行增刪改查

執(zhí)行了上面的操作且數(shù)據(jù)庫(kù)已open,就能使用QSqlQuery的exec方法來(lái)完成增刪改查了。

//插入數(shù)據(jù)
void insertRecord(const QString &name, int age)
{
    QSqlQuery query;
    //方式一,直接執(zhí)行SQL語(yǔ)句
    query.exec(QString(R"(INSERT INTO my_table(name,age) VALUES('%1',%2);)")
               .arg(name).arg(age));
    //方式二,綁定值,待定變量默認(rèn)用問號(hào)占位,注意字符串也沒有引號(hào)
    /*query.prepare(R"(INSERT INTO my_table(name,age) VALUES(?,?);)");
    query.addBindValue(name);
    query.addBindValue(age);
    query.exec();*/
}
 
//刪除數(shù)據(jù)
void deleteRecord(const QString &name)
{
    QSqlQuery query;
    //方式一,直接執(zhí)行SQL語(yǔ)句
    query.exec(QString(R"(DELETE FROM my_table WHERE name='%1';)")
               .arg(name));
    //方式二,綁定值,待定變量默認(rèn)用問號(hào)占位
    /*query.prepare(R"(DELETE FROM my_table WHERE name=?;)");
    query.addBindValue(name);
    query.exec();*/
}
 
//更新數(shù)據(jù)
void updateRecord(const QString &name, int age)
{
    QSqlQuery query;
    //方式一,直接執(zhí)行SQL語(yǔ)句
    query.exec(QString(R"(UPDATE my_table SET age=%2 WHERE name='%1';)")
               .arg(name).arg(age));
    //方式二,綁定值,待定變量默認(rèn)問號(hào),可自定義
    /*query.prepare(R"(UPDATE my_table SET age=:age WHERE name=:name;)");
    query.bindValue(":name",name);//通過自定義的別名來(lái)替代
    query.bindValue(":age",age);
    query.exec();*/
}
 
//查詢數(shù)據(jù)
int searchRecord(const QString &name)
{
    QSqlQuery query;
    query.exec(QString(R"(SELECT age FROM my_table WHERE name='%1';)")
               .arg(name));
 
    //獲取查詢結(jié)果的第0個(gè)值,
    //如果結(jié)果是多行數(shù)據(jù),可用while(query.next()){}遍歷每一行
    int ageValue=-1;
    if(query.next()){
        ageValue=query.value(0).toInt();
    }
    qDebug()<<ageValue;
    return ageValue;
}

可以看到,如果熟悉SQL語(yǔ)句的話,很容易就實(shí)現(xiàn)了增刪改查功能。

對(duì)于 BLOB 類型,查詢后可以 toByteArray,修改時(shí)可以 bindValue QByteArray。

5.進(jìn)階

有時(shí)候會(huì)遇到大量數(shù)據(jù)操作的情況,這時(shí)候用普通的insert之類的語(yǔ)句循環(huán)操作可能會(huì)很慢。

技巧一:開啟事務(wù)

SQLite通過執(zhí)行”BEGIN;“或是”BEGIN TRANSACTION;“開啟事務(wù),執(zhí)行”ROLLBACK;“進(jìn)行回滾,執(zhí)行”COMMIT;“或是”END TRANSACTION;“提交事務(wù)。QSqlDatabase也提供了對(duì)應(yīng)的transaction、rollback、commit三個(gè)函數(shù)來(lái)執(zhí)行對(duì)應(yīng)操作。

技巧二:關(guān)閉寫同步(synchrnous)

在SQLite中,數(shù)據(jù)庫(kù)配置的參數(shù)都由編譯指示(pragma)來(lái)實(shí)現(xiàn)的,而其中synchronous選項(xiàng)有三種可選狀態(tài),分別是full、normal、off。簡(jiǎn)要說(shuō)來(lái),full寫入速度最慢,但保證數(shù)據(jù)是安全的,不受斷電、系統(tǒng)崩潰等影響,而off可以加速數(shù)據(jù)庫(kù)的一些操作,但如果系統(tǒng)崩潰或斷電,則數(shù)據(jù)庫(kù)可能會(huì)損毀。通過執(zhí)行”PRAGMA synchronous = OFF;“語(yǔ)句,可以提升效率,不過若不是臨時(shí)數(shù)據(jù)庫(kù)不建議此操作。

SQLite 默認(rèn)是文件鎖, Qt 中 SQLite 默認(rèn)是以多線程讀寫模式打開,如果同時(shí)寫入就會(huì)出現(xiàn)寫入錯(cuò)誤:

可以將寫操作上鎖,但是實(shí)測(cè)線程中循環(huán)寫入時(shí),只讀打開去查詢也是會(huì)阻塞很久,毫秒到幾秒不等,這時(shí)候就得把超時(shí)設(shè)置長(zhǎng)一點(diǎn)。

所以還是得讀寫都加鎖,但這也只能解決單個(gè)進(jìn)程的并發(fā)訪問。

到此這篇關(guān)于Qt操作SQLite數(shù)據(jù)庫(kù)的教程詳解的文章就介紹到這了,更多相關(guān)Qt操作SQLite數(shù)據(jù)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Qt實(shí)現(xiàn)可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器

    Qt實(shí)現(xiàn)可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器

    計(jì)算器是我們生活中很常見的東西,它可以由多種語(yǔ)言多種方式來(lái)實(shí)現(xiàn)。本文主要介紹的是基于C++語(yǔ)言,由QT實(shí)現(xiàn)的可以計(jì)算大數(shù)的簡(jiǎn)單計(jì)算器,需要的可以參考一下
    2022-12-12
  • c++中l(wèi)og4cplus日志庫(kù)使用的基本步驟和示例代碼

    c++中l(wèi)og4cplus日志庫(kù)使用的基本步驟和示例代碼

    這篇文章主要給大家介紹了關(guān)于c++中l(wèi)og4cplus日志庫(kù)使用的相關(guān)資料,log4cplus是一款開源的c++日志庫(kù),具有線程安全,靈活,以及多粒度控制的特點(diǎn),log4cplus可以將日志按照優(yōu)先級(jí)進(jìn)行劃分,使其可以面向程序的調(diào)試,運(yùn)行,測(cè)試,后期維護(hù)等軟件全生命周期,需要的朋友可以參考下
    2024-06-06
  • C++實(shí)現(xiàn)簡(jiǎn)易的彈球小游戲

    C++實(shí)現(xiàn)簡(jiǎn)易的彈球小游戲

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)易的彈球小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C++回溯與分支限界算法分別解決背包問題詳解

    C++回溯與分支限界算法分別解決背包問題詳解

    給定n種物品和一背包。物品i的重量是wi,其價(jià)值為vi,背包的容量為C。問應(yīng)如何選擇裝入背包的物品,使得裝入背包中物品的總價(jià)值最大?下面我們分別用回溯與分支限界方法解決
    2022-06-06
  • opencv學(xué)習(xí)筆記C++繪制灰度直方圖

    opencv學(xué)習(xí)筆記C++繪制灰度直方圖

    這篇文章主要為大家介紹了opencv學(xué)習(xí)筆記C++繪制灰度直方圖的實(shí)現(xiàn)代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • OpenCV利用K-means實(shí)現(xiàn)根據(jù)顏色進(jìn)行圖像分割

    OpenCV利用K-means實(shí)現(xiàn)根據(jù)顏色進(jìn)行圖像分割

    K-means是一種經(jīng)典的無(wú)監(jiān)督聚類算法---不需要人工干預(yù)。本文將通過K-means算法實(shí)現(xiàn)根據(jù)顏色進(jìn)行圖像分割的效果,感興趣的小伙伴可以嘗試一下
    2022-10-10
  • OpenCV使用稀疏光流實(shí)現(xiàn)視頻對(duì)象跟蹤的方法詳解

    OpenCV使用稀疏光流實(shí)現(xiàn)視頻對(duì)象跟蹤的方法詳解

    這篇文章主要為大家詳細(xì)介紹了OpenCV如何使用稀疏光流實(shí)現(xiàn)視頻對(duì)象跟蹤功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下
    2023-02-02
  • C++精要分析右值引用與完美轉(zhuǎn)發(fā)的應(yīng)用

    C++精要分析右值引用與完美轉(zhuǎn)發(fā)的應(yīng)用

    C++11標(biāo)準(zhǔn)為C++引入右值引用語(yǔ)法的同時(shí),還解決了一個(gè)短板,即使用簡(jiǎn)單的方式即可在函數(shù)模板中實(shí)現(xiàn)參數(shù)的完美轉(zhuǎn)發(fā)。那么,什么是完美轉(zhuǎn)發(fā)?它為什么是C++98/03 標(biāo)準(zhǔn)存在的一個(gè)短板?C++11標(biāo)準(zhǔn)又是如何為C++彌補(bǔ)這一短板的?別急,本節(jié)將就這些問題給讀者做一一講解
    2022-05-05
  • C/C++?extern關(guān)鍵字用法示例全面解析

    C/C++?extern關(guān)鍵字用法示例全面解析

    這篇文章主要為大家介紹了C/C++?extern關(guān)鍵字用法示例全面解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 詳解C語(yǔ)言中的動(dòng)態(tài)內(nèi)存管理

    詳解C語(yǔ)言中的動(dòng)態(tài)內(nèi)存管理

    對(duì)于數(shù)據(jù)的存儲(chǔ)我們可以靜態(tài)存儲(chǔ),也可以動(dòng)態(tài)存儲(chǔ),兩種方式都有自己特有的好處,這篇文章教我們?nèi)绾瓦M(jìn)行動(dòng)態(tài)的數(shù)據(jù)存儲(chǔ)?。。?!感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-12-12

最新評(píng)論