久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Qt 學(xué)習(xí)之路 2(55):數(shù)據(jù)庫操作 | DevBean's World

 dwlinux_gs 2014-08-18

Qt 提供了 QtSql 模塊來提供平臺獨立的基于 SQL 的數(shù)據(jù)庫操作,。這里我們所說的“平臺獨立”,,既包括操作系統(tǒng)平臺,有包括各個數(shù)據(jù)庫平臺,。另外,,我們強調(diào)了“基于 SQL”,因為 NoSQL 數(shù)據(jù)庫至今沒有一個通用查詢方法,,所以不可能提供一種通用的 NoSQL 數(shù)據(jù)庫的操作,。Qt 的數(shù)據(jù)庫操作還可以很方便的與 model/view 架構(gòu)進行整合。通常來說,我們對數(shù)據(jù)庫的操作更多地在于對數(shù)據(jù)庫表的操作,,而這正是 model/view 架構(gòu)的長項,。

Qt 使用QSqlDatabase表示一個數(shù)據(jù)庫連接。更底層上,,Qt 使用驅(qū)動(drivers)來與不同的數(shù)據(jù)庫 API 進行交互,。Qt 桌面版本提供了如下幾種驅(qū)動:

 驅(qū)動 數(shù)據(jù)庫
QDB2 IBM DB2 (7.1 或更新版本)
QIBASE Borland InterBase
QMYSQL MySQL
QOCI Oracle Call Interface Driver
QODBC Open Database Connectivity (ODBC) – Microsoft SQL Server 及其它兼容 ODBC 的數(shù)據(jù)庫
QPSQL PostgreSQL (7.3 或更新版本)
QSQLITE2 SQLite 2
QSQLITE SQLite 3
QSYMSQL 針對 Symbian 平臺的SQLite 3
QTDS Sybase Adaptive Server (自 Qt 4.7 起廢除)

不過,由于受到協(xié)議的限制,,Qt 開源版本并沒有提供上面所有驅(qū)動的二進制版本,,而僅僅以源代碼的形式提供。通常,,Qt 只默認搭載 QSqlite 驅(qū)動(這個驅(qū)動實際還包括 Sqlite 數(shù)據(jù)庫,,也就是說,如果需要使用 Sqlite 的話,,只需要該驅(qū)動即可),。我們可以選擇把這些驅(qū)動作為 Qt 的一部分進行編譯,也可以當(dāng)作插件編譯,。

如果習(xí)慣于使用 SQL 語句,,我們可以選擇QSqlQuery類;如果只需要使用高層次的數(shù)據(jù)庫接口(不關(guān)心 SQL 語法),,我們可以選擇QSqlTableModelQSqlRelationalTableModel,。本章我們介紹QSqlQuery類,在后面的章節(jié)則介紹QSqlTableModelQSqlRelationalTableModel,。

在使用時,,我們可以通過

1
QSqlDatabase::drivers();

找到系統(tǒng)中所有可用的數(shù)據(jù)庫驅(qū)動的名字列表。我們只能使用出現(xiàn)在列表中的驅(qū)動,。由于默認情況下,,QtSql 是作為 Qt 的一個模塊提供的。為了使用有關(guān)數(shù)據(jù)庫的類,,我們必須早 .pro 文件中添加這么一句:

1
QT += sql

這表示,,我們的程序需要使用 Qt 的 core、gui 以及 sql 三個模塊,。注意,,如果需要同時使用 Qt4 和 Qt5 編譯程序,通常我們的 .pro 文件是這樣的:

1
2
QT += core gui sql
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

這兩句也很明確:Qt 需要加載 core,、gui 和 sql 三個模塊,,如果主板本大于 4,則再添加 widgets 模塊,。

下面來看一個簡單的函數(shù):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool connect(const QString &dbName)
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
//    db.setHostName("host");
//    db.setDatabaseName("dbname");
//    db.setUserName("username");
//    db.setPassword("password");
    db.setDatabaseName(dbName);
    if (!db.open()) {
        QMessageBox::critical(0, QObject::tr("Database Error"),
                              db.lastError().text());
        return false;
    }
    return true;
}

我們使用connect()函數(shù)創(chuàng)建一個數(shù)據(jù)庫連接,。我們使用QSqlDatabase::addDatabase()靜態(tài)函數(shù)完成這一請求,,也就是創(chuàng)建了一個QSqlDatabase實例。注意,,數(shù)據(jù)庫連接使用自己的名字進行區(qū)分,,而不是數(shù)據(jù)庫的名字。例如,,我們可以使用下面的語句:

1
QSqlDatabase db=QSqlDatabase::addDatabase("QSQLITE", QString("con%1").arg(dbName));

此時,,我們是使用addDatabase()函數(shù)的第二個參數(shù)來給這個數(shù)據(jù)庫連接一個名字。在這個例子中,,用于區(qū)分這個數(shù)據(jù)庫連接的名字是QString("conn%1").arg(dbName),,而不是 “QSQLITE”。這個參數(shù)是可選的,,如果不指定,系統(tǒng)會給出一個默認的名字QSqlDatabase::defaultConnection,,此時,,Qt 會創(chuàng)建一個默認的連接。如果你給出的名字與已存在的名字相同,,新的連接會替換掉已有的連接,。通過這種設(shè)計,我們可以為一個數(shù)據(jù)庫建立多個連接,。

我們這里使用的是 sqlite 數(shù)據(jù)庫,,只需要指定數(shù)據(jù)庫名字即可。如果是數(shù)據(jù)庫服務(wù)器,,比如 MySQL,,我們還需要指定主機名、端口號,、用戶名和密碼,,這些語句使用注釋進行了簡單的說明。

接下來我們調(diào)用了QSqlDatabase::open()函數(shù),,打開這個數(shù)據(jù)庫連接,。通過檢查open()函數(shù)的返回值,我們可以判斷數(shù)據(jù)庫是不是正確打開,。

QtSql 模塊中的類大多具有lastError()函數(shù),,用于檢查最新出現(xiàn)的錯誤。如果你發(fā)現(xiàn)數(shù)據(jù)庫操作有任何問題,,應(yīng)該使用這個函數(shù)進行錯誤的檢查,。這一點我們也在上面的代碼中進行了體現(xiàn)。當(dāng)然,,這只是最簡單的實現(xiàn),,一般來說,,更好的設(shè)計是,不要在數(shù)據(jù)庫操作中混雜界面代碼(并且將這個connect()函數(shù)放在一個專門的數(shù)據(jù)庫操作類中),。

接下來我們可以在main()函數(shù)中使用這個connect()函數(shù):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    if (connect("demo.db")) {
        QSqlQuery query;
        if (!query.exec("CREATE TABLE student ("
                        "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                        "name VARCHAR,"
                        "age INT)")) {
            QMessageBox::critical(0, QObject::tr("Database Error"),
                                  query.lastError().text());
            return 1;
        }
    } else {
        return 1;
    }
    return a.exec();
}

main()函數(shù)中,,我們調(diào)用這個connect()函數(shù)打開數(shù)據(jù)庫。如果打開成功,,我們通過一個QSqlQuery實例執(zhí)行了 SQL 語句,。同樣,我們使用其lastError()函數(shù)檢查了執(zhí)行結(jié)果是否正確,。

注意這里的QSqlQuery實例的創(chuàng)建,。我們并沒有指定是為哪一個數(shù)據(jù)庫連接創(chuàng)建查詢對象,此時,,系統(tǒng)會使用默認的連接,,也就是使用沒有第二個參數(shù)的addDatabase()函數(shù)創(chuàng)建的那個連接(其實就是名字為QSqlDatabase::defaultConnection的默認連接)。如果沒有這么一個連接,,系統(tǒng)就會報錯,。也就是說,如果沒有默認連接,,我們在創(chuàng)建QSqlQuery對象時必須指明是哪一個QSqlDatabase對象,,也就是addDatabase()的返回值。

我們還可以通過使用QSqlQuery::isActive()函數(shù)檢查語句執(zhí)行正確與否,。如果QSqlQuery對象是活動的,,該函數(shù)返回 true。所謂“活動”,,就是指該對象成功執(zhí)行了exec()函數(shù),,但是還沒有完成。如果需要設(shè)置為不活動的,,可以使用finish()或者clear()函數(shù),,或者直接釋放掉這個QSqlQuery對象。這里需要注意的是,,如果存在一個活動的 SELECT 語句,,某些數(shù)據(jù)庫系統(tǒng)不能成功完成connect()或者rollback()函數(shù)的調(diào)用。此時,,我們必須首先將活動的 SELECT 語句設(shè)置成不活動的,。

創(chuàng)建過數(shù)據(jù)庫表 student 之后,我們開始插入數(shù)據(jù),,然后將其獨取出來:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if (connect("demo.db")) {
    QSqlQuery query;
    query.prepare("INSERT INTO student (name, age) VALUES (?, ?)");
    QVariantList names;
    names << "Tom" << "Jack" << "Jane" << "Jerry";
    query.addBindValue(names);
    QVariantList ages;
    ages << 20 << 23 << 22 << 25;
    query.addBindValue(ages);
    if (!query.execBatch()) {
        QMessageBox::critical(0, QObject::tr("Database Error"),
                              query.lastError().text());
    }
    query.finish();
    query.exec("SELECT name, age FROM student");
    while (query.next()) {
        QString name = query.value(0).toString();
        int age = query.value(1).toInt();
        qDebug() << name << ": " << age;
    }
} else {
    return 1;
}

依舊連接到我們創(chuàng)建的 demo.db 數(shù)據(jù)庫,。我們需要插入多條數(shù)據(jù),此時可以使用QSqlQuery::exec()函數(shù)一條一條插入數(shù)據(jù),,但是這里我們選擇了另外一種方法:批量執(zhí)行,。首先,,我們使用QSqlQuery::prepare()函數(shù)對這條 SQL 語句進行預(yù)處理,問號 ? 相當(dāng)于占位符,,預(yù)示著以后我們可以使用實際數(shù)據(jù)替換這些位置,。簡單說明一下,預(yù)處理是數(shù)據(jù)庫提供的一種特性,,它會將 SQL 語句進行編譯,,性能和安全性都要優(yōu)于普通的 SQL 處理。在上面的代碼中,,我們使用一個字符串列表 names 替換掉第一個問號的位置,,一個整型列表 ages 替換掉第二個問號的位置,利用QSqlQuery::addBindValue()我們將實際數(shù)據(jù)綁定到這個預(yù)處理的 SQL 語句上,。需要注意的是,,names 和 ages 這兩個列表里面的數(shù)據(jù)需要一一對應(yīng)。然后我們調(diào)用QSqlQuery::execBatch()批量執(zhí)行 SQL,,之后結(jié)束該對象,。這樣,插入操作便完成了,。

另外說明一點,我們這里使用了 ODBC 風(fēng)格的 ? 占位符,,同樣,,我們也可以使用 Oracle 風(fēng)格的占位符:

1
query.prepare("INSERT INTO student (name, age) VALUES (:name, :age)");

此時,我們就需要使用

1
2
query.bindValue(":name", names);
query.bindValue(":age", ages);

進行綁定,。Oracle 風(fēng)格的綁定最大的好處是,,綁定的名字和值很清晰,與順序無關(guān),。但是這里需要注意,,bindValue()函數(shù)只能綁定一個位置。比如

1
2
3
query.prepare("INSERT INTO test (name1, name2) VALUES (:name, :name)");
// ...
query.bindValue(":name", name);

只能綁定第一個 :name 占位符,,不能綁定到第二個,。

接下來我們依舊使用同一個查詢對象執(zhí)行一個 SELECT 語句。如果存在查詢結(jié)果,,QSqlQuery::next()會返回 true,,直到到達結(jié)果最末,返回 false,,說明遍歷結(jié)束,。我們利用這一點,使用 while 循環(huán)即可遍歷查詢結(jié)果,。使用QSqlQuery::value()函數(shù)即可按照 SELECT 語句的字段順序獲取到對應(yīng)的數(shù)據(jù)庫存儲的數(shù)據(jù),。

對于數(shù)據(jù)庫事務(wù)的操作,,我們可以使用 QSqlDatabase::transaction() 開啟事務(wù),QSqlDatabase::commit() 或者QSqlDatabase::rollback() 結(jié)束事務(wù),。使用QSqlDatabase::database()函數(shù)則可以根據(jù)名字獲取所需要的數(shù)據(jù)庫連接,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多