qt學習筆記(八)之深入QSqlQuery

在上一節中,我們直接調用QSqlQuery:exec()對數據庫進行增刪改查等簡單操作。

在項目開發中,爲了實現系統的低耦合,我們就必須封裝出一個數據庫功能模塊。

一、prepare()

首先創建一個頭文件"attend_db.h"。

初始化數據庫操作,包括創建數據庫文件、建表、以及添加一些基礎數據。最好還要返回數據庫操作的一些信息(最重要的是錯誤信息)。

QSqlError db_Init()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:"); //使用內存數據庫

    if(!db.open())
    {
        //打開失敗
        return db.lastError();
    }

    QSqlQuery query;
    //創建組別表,人員表,考勤記錄表
    if(!query.exec("CREATE TABLE table_group(group_id INTEGER PRIMARY KEY, group_name VARCHAR)"))
    {
        return query.lastError();
    }
    if(!query.exec("CREATE TABLE table_user(user_id VARCHAR PRIMARY KEY, group_id INTEGER)"))
    {
        return query.lastError();
    }
    if(!query.exec("CREATE TABLE table_record(user_id VARCHAR, datetime VARCHAR)"))
    {
        return query.lastError();
    }
    //添加組別數據
    if(!query.prepare("INSERT INTO table_group(group_id, group_name) VALUES(:gourp_id, :group_name)"))
    {
        return query.lastError();
    }

    db_AddGroup(query, 1, "student");
    db_AddGroup(query, 2, "teacher");

    //添加人員數據
    if(!query.prepare("INSERT INTO table_user(user_id, group_id) VALUES(:user_id, :group_id)"))
    {
        return query.lastError();
    }

    db_AddUser(query, "T0001", 2);
    qdb_AddUser(query, "T0002", 2);
    db_AddUser(query, "S111201", 1);

    //添加考勤記錄數據
    if(!query.prepare("INSERT INTO table_record(user_id, datetime) VALUES(:user_id, :datetime)"))
    {
        return query.lastError();
    }

    db_AddRecord(query, "T0001", QDateTime::currentDateTime());
    db_AddRecord(query, "T0002", QDateTime::currentDateTime());
    db_AddRecord(query, "S111201", QDateTime::currentDateTime());

    return QSqlError();
}
這裏對錶的添加數據不再簡單的使用QSqlQuery:exec()直接執行語句了。爲了模塊化,我們還要封裝出對錶數據的操作函數(包括增刪改查)。

提供對外的接口供上層應用使用。形參最好就僅僅是表的參量,這樣清晰明瞭。

Qt提供了bool prepare(const QString& query)接口。(SQLite也提供了該API函數)

query.prepare("INSERT INTO table_group(group_id, group_name) VALUES(:gourp_id, :group_name)")
我們先使用了prepare()函數,在其中利用了“:group_id”和“:group_name”來代替具體的數據,之後就可以利用bindValue()函數給group_idgroup_name兩個屬性賦值,這稱爲綁定操作。

例:

    query.bindValue(0, 1);
    query.bindValue(1, 'student');

其中編號0和1分別代表“:group_id”和“:group_name”,就是說按照prepare()函數中出現的屬性從左到右編號,最左邊是0 。這裏的“:group_id”和“:group_name”,叫做佔位符,這是ODBC數據庫的表示方法,還有一種Oracle的表示方法就是全部用“?”號。

query.prepare("INSERT INTO table_group(group_id, group_name) VALUES(?, ?)")

這是對單條記錄的綁定,當然綁定完還是要調用exec()的,否則語句不會被執行。

當用ODBC的表示方法時,我們也可以將編號用實際的佔位符代替。這裏就不具體介紹了。

我們也可以進行批量處理

 void addBindValue(const QVariant& val, QSql::ParamType type = QSql::In);
通過調用addBindValue()增加值val值列表。
    QVariantList GroupIDs;
    GroupIDs << 1 << 2;
    QVariantList GroupNames;
    GroupNames << "student" << "teacher";

    query.addBindValue(GroupIDs);
    query.addBindValue(GroupNames);
    query.execBatch();
查看下ececBatch()的文檔。

/*

Executes a previously prepared SQL query in a batch. All the bound parameters have to be lists of variants. If the database doesn't support batch executions, the driver will simulate it using conventional exec() calls.

*/

如果數據庫不支持批量處理,則用exec()來代替。

二、執行SQL語句後返回的結果集

/*下文不是原創、存屬轉載*/

結果集其實就是查詢到的所有記錄的集合,而在QSqlQuery類中提供了多個函數來操作這個集合,需要注意這個集合中的記錄是從0開始編號的。最常用的有:

seek(int n) :query指向結果集的第n條記錄。

first() :query指向結果集的第一條記錄。

last() :query指向結果集的最後一條記錄。

next() :query指向下一條記錄,每執行一次該函數,便指向相鄰的下一條記錄。

previous() :query指向上一條記錄,每執行一次該函數,便指向相鄰的上一條記錄。

record() :獲得現在指向的記錄。

value(int n) :獲得屬性的值。其中n表示你查詢的第n個屬性,比方我們使用“select * from student”就相當於“select id, name from student”,那麼value(0)返回id屬性的值,value(1)返回name屬性的值。該函數返回QVariant類型的數據,關於該類型與其他類型的對應關係,可以在幫助中查看QVariant。

at() :獲得現在query指向的記錄在結果集中的編號。

需要說明,當剛執行完query.exec(“select * from student”);這行代碼時,query是指向結果集以外的,我們可以利用query.next(),當第一次執行這句代碼時,query便指向了結果集的第一條記錄。當然我們也可以利用seek(0)函數或者first()函數使query指向結果集的第一條記錄。但是爲了節省內存開銷,推薦的方法是,在query.exec(“select * from student”);這行代碼前加上query.setForwardOnly(true);這條代碼,此後只能使用next()和seek()函數。

基友們。~~神棍節快樂。


在這裏附上程序源代碼下載鏈接:qt_深入QSqlQuery

以上純屬個人學習筆記,如果哪裏錯了,希望提出。願和大家一起共同學習,一起進步。我的郵箱地址是:[email protected]



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章