qt數據庫的操作

理一下 QT 操作數據庫的一些要點,以備以後的查詢學習(主要是操作 mysql )。

 

首先,要查詢相關的驅動是否已經裝好了,可以用以下的程序進行驗證:

 

#include <QtCore/QCoreApplication>

#include <QSqlDatabase>

#include <QDebug>

#include <QStringList>

int main(int argc, char *argv[])

{

    QCoreApplication a(argc, argv);

    qDebug()<<"Available drivers:";

    QStringList drivers = QSqlDatabase::drivers();

    foreach(QString driver, drivers)

     qDebug() <<"/t" << driver;

    return a.exec();

}

 

結果如下:


 

接着是連接數據庫:

#include <QtGui/QApplication>

#include <QtGui>

#include <QtSql>

bool createConnection()

{

    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");

    db.setDatabaseName("test");

    db.setUserName("root");

    db.setPassword("123456");

    bool ok = db.open();

    if(!ok){

        QMessageBox::critical(0, QObject::tr(" 連接數據庫失敗!!! "), db.lastError().text());

        return false;

    }else{

        QMessageBox::information(0, QObject::tr("Tips"), QObject::tr(" 連接數據庫成功!!! "));

        return true;

    }

}

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    QTextCodec *codec= QTextCodec::codecForName("GB2312");

    QTextCodec::setCodecForLocale(codec);

    QTextCodec::setCodecForCStrings(codec);

    QTextCodec::setCodecForTr(codec);

    if(!createConnection())

        return 1;

    return a.exec();

}

 

結果如下:


 

 

插入操作:

//ODBC 數據庫表示方式

QSqlQuery query;
query.prepare(
insert into student (id, name)
                 
values (:id, :name));
query.bindValue(0, 5);
query.bindValue(1,
sixth);
query.exec();

 

 

//Oracle 表示方式

query.prepare( insert into student (id, name)
                 
values (?, ?));
query.bindValue(0, 5);
query.bindValue(1,
sixth);
query.exec();

 

// 使用 addBindValue() 函數,省去了編號,它是按屬性順序賦值的

query.prepare( insert into student (id, name)
                 
values (?, ?));
query.addBindValue(5);
query.addBindValue(
sixth);
query.exec();

 

// 使用 ODBC 方法時,可以將編號用實際的佔位符代替

query.prepare( insert into student (id, name)
                     
values (:id, :name));
query.bindValue(
:id, 5);
query.bindValue(
:name, sixth);
query.exec();

注意:最後一定要執行 exec() ,否則上面的語句是不會被執行的。

 

 

// 進行多個記錄的插入時,可以利用綁定進行批處理

QSqlQuery q;
q.prepare(
insert into student values (?, ?));

QVariantList ints;
ints << 10 << 11 << 12 << 13;
q.addBindValue(ints);

QVariantList names;
names <<
xiaoming << xiaoliang << xiaogang << QVariant(QVariant::String);
//
最後一個是空字符串,應與前面的格式相同

q.addBindValue(names);

if (!q.execBatch()) // 進行批處理,如果出錯就輸出錯誤
        qDebug() << q.lastError();

 

查詢操作:

 

// 返回全部的屬性和結果集

 

QSqlQuery query;
query.exec(
select * from student);// 執行查詢操作
qDebug() <<
exec next() :;
if(query.next())
//
開始就先執行一次next() 函數,那麼query 指向結果集的第一條記錄

{
        int rowNum = query.at();
        // 獲取query 所指向的記錄在結果集中的編號
        int columnNum = query.record().count();
        // 獲取每條記錄中屬性(即列)的個數
        int fieldNo = query.record().indexOf( name);
        // 獲取 name ”屬性所在列的編號,列從左向右編號,最左邊的編號爲 0
        int id = query.value(0).toInt();
        // 獲取id 屬性的值,並轉換爲int
       QString name = query.value(fieldNo).toString();
        // 獲取name 屬性的值
        qDebug() << rowNum is : << rowNum // 將結果輸出
                << id is : << id
               <<
name is : <<name
               <<
columnNum is : << columnNum;
}
qDebug() <<
exec seek(2) :;
if(query.seek(2))
//
定位到結果集中編號爲2 的記錄,即第三條記錄,因爲第一條記錄的編號爲
0
{
        qDebug() <<
rowNum is : <<query.at()
               <<
id is : <<query.value(0).toInt()
               <<
name is : <<query.value(1).toString();
}
qDebug() <<
exec last() :;
if(query.last())
//
定位到結果集中最後一條記錄

{
        qDebug() <<
rowNum is : <<query.at()
               <<
id is : << query.value(0).toInt()
               <<
name is : <<query.value(1).toString();
}

 

結果集其實就是查詢到的所有記錄的集合,而在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() 函數。

 

 

// 滿足一定條件的結果集,方法一

 

QSqlQuery query;
query.prepare(
select name from student where id = ?);
int id =2; //
從界面獲取id 的值

query.addBindValue(id); // id 值進行綁定
query.exec();
query.next(); //
指向第一條記錄
qDebug() << query.value(0).toString();

 

// 方法二

QSqlQuery query;

query. exec( QObject :: tr( "select * from student where id = %1" ). arg( 2 ));

if (! query. next())

        qDebug()<< "none" ;

else

        qDebug()<< query. value( 0 ). toInt()<< query. value( 1 ). toString();

 

 

 

 

事務是數據庫的一個重要功能,所謂事務是用戶定義的一個數據庫操作序列,這些操作要麼全做要麼全不做,是一個不可分割的工作單位。在Qt 中用transaction() 開始一個事務操作,用commit() 函數或rollback() 函數進行結束。commit() 表示提交,即提交事務的所有操作。具體地說就是將事務中所有對數據庫的更新寫回到數據庫,事務正常結束。rollback() 表示回滾,即在事務運行的過程中發生了某種故障,事務不能繼續進行,系統將事務中對數據庫的所有已完成的操作全部撤銷,回滾到事務開始時的狀態。

 

QSqlQuery query;
if(QSqlDatabase::database().transaction()) //
啓動事務操作
  {
       //
下面執行各種數據庫操作
            query.exec( insert into student values (14, ‘hello’));
      query.exec(
delete from student where id = 1);
    
       //
            if(!QSqlDatabase::database().commit())
      {
                qDebug() << QSqlDatabase::database().lastError(); //
提交
                         if(!QSqlDatabase::database().rollback())
                    qDebug() << QSqlDatabase::database().lastError(); //
回滾
            }
}
//
輸出整張表
query.exec( select * from student);
while(query.next())
     qDebug() << query.value(0).toInt() << query.value(1).toString();

 

 

Qt 中使用了自己的機制來避免使用SQL 語句,它爲我們提供了更簡單的數據庫操作和數據顯示模型。它們分別是隻讀的QSqlQueryModel ,操作單表的QSqlTableModel 和以及可以支持外鍵的QSqlRelationalTableModel

 

// QSqlQueryModel

QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery(
select * from student);
model->setHeaderData(0, Qt::Horizontal, tr(
id));
model->setHeaderData(1, Qt::Horizontal, tr(
name));
QTableView *view = new QTableView;
view->setModel(model);
view->show();


 

//QSqlTableModel

QSqlTableModel *model;

model = new QSqlTableModel(this);
model->setTable(
student);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select(); //
選取整個表的所有行

// model->removeColumn(1); // 不顯示name 屬性列 , 如果這時添加記錄,則該屬性的值添加不上
ui->tableView->setModel(model);
// ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);   //
使其不可編輯

 

 

// 過濾

model->setFilter(QObject::tr(“name = ‘%1 ”).arg(name)); // 根據姓名進行篩選
model->select(); // 顯示結果

// 刪除操作

int curRow = ui->tableView->currentIndex().row();
    // 獲取選中的行
model->removeRow(curRow);
    // 刪除該行
int ok = QMessageBox::warning(this,tr( “刪除當前行!),tr( “你確定
                                                           “刪除當前行嗎? ),
                         QMessageBox::Yes,QMessageBox::No);
if(ok == QMessageBox::No)
{

       model->revertAll(); // 如果不刪除,則撤銷
}
else

model->submitAll(); // 否則提交,在數據庫中刪除該行

 

// 插入操作

int rowNum = model->rowCount(); // 獲得表的行數
int id = 10;
model->insertRow(rowNum); // 添加一行
model->setData(model->index(rowNum,0),id);

model->submitAll();// 記得提交

 

 

//QSqlRelationalTableModel

// create table student (id int primary key, name vchar,course int)

// create table course (id int primary key, name vchar, teacher vchar)

model = new QSqlRelationalTableModel(this);
model->setEditStrategy(QSqlTableModel::OnFieldChange); //
屬性變化時寫入數據庫
model->setTable( student);
model->setRelation(2,QSqlRelation(
course,id,name));
//
student 表的第三個屬性設爲course 表的id 屬性的外鍵,並將其顯示爲course 表的name 屬性的值

model->setHeaderData(0, Qt::Horizontal, QObject::tr( ID));
model->setHeaderData(1, Qt::Horizontal, QObject::tr(
Name));
model->setHeaderData(2, Qt::Horizontal, QObject::tr(
Course));
model->select();
ui->tableView->setModel(model);

ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView));// 如果用戶更改課程屬性,那麼他只能在課程表中有的課程中進行選擇,而不能隨意填寫課程。在Qt 中的QSqlRelationalDelegate 委託類就能實現這個功能。我們只需添加一行代碼

 

 

該文是根據http://hi.baidu.com/yafeilinux/上的資料整理的

 

 

發佈了92 篇原創文章 · 獲贊 11 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章