Qt数据库:(四)利用QSqlQuery类执行SQL语句(二)

时间:2022-08-26 10:51:50

接着上一篇教程。

二,在SQL语句中使用变量。

我们先看下面的一个例子,将“查询”按钮的槽函数更改如下:

void Widget::on_pushButton_clicked()
{
 QSqlQuery query;
 query.prepare("insert into person(id, firstname,lastname) "
 "values (:id, :firstname,:lastname)");
 query.bindValue(0, 106);
 query.bindValue(1, "liu");
 query.bindValue(2,"mike");
 query.exec();
 //下面输出最后一条记录
 query.exec("select * from person");
 query.last();
 int id = query.value(0).toInt();
 QString firstname = query.value(1).toString();
 QString lastname = query.value(2).toString();
 qDebug() << id << firstname << lastname;
}
 

运行效果如下:

Qt数据库:(四)利用QSqlQuery类执行SQL语句(二)

可以看到,在student表的最后又添加了一条记录。在上面的程序中,我们先使用了prepare()函数,在其中利用了“:id”、“:firstname”、“:lastname”来代替具体的数据,而后又利用bindValue()函数给id、firstname和lastname三个属性赋值,这称为绑定操作。其中编号0、1和2分别代表“:id”、“:firstname”和“:lastname”,就是说按照prepare()函数中出现的属性从左到右编号,最左边是0 。这里的“:id”、“:firstname”和“:lastname”,叫做占位符,这是ODBC数据库的表示方法,还有一种Oracle的表示方法就是全部用“?”号。如下:

query.prepare("insert into person(id, firstname,lastname) "
 "values (?,?,?)");
query.bindValue(0, 106);
query.bindValue(1, "liu");
query.bindValue(2,"mike");
query.exec();

我们也可以利用addBindValue()函数,这样就可以省去编号,它是按顺序给属性赋值的,如下:

query.prepare("insert into person(id, firstname,lastname) "
 "values (?,?,?)");
query.addBindValue("106");
query.addBindValue("liu");
query.addBindValue("mike");
query.exec();

当用ODBC的表示方法时,我们也可以将编号用实际的占位符代替,如下:

query.prepare("insert into person(id, firstname,lastname) "
 "values (:id, :firstname,:lastname)");
query.bindValue(":id", 106);
query.bindValue(":firstname", "liu");
query.bindValue(":lastname","mike");
query.exec();

以上各种形式的表示方式效果是一样的。特别注意,在最后一定要执行exec()函数,所做的操作才能被真正执行。

下面我们就可以利用绑定操作在SQL语句中使用变量了。

void Widget::on_pushButton_clicked()
{
     QSqlQuery query;
    query.prepare("select firstname from person where id = ?");

int id = ui->spinBox->value(); //从界面获取id的值

query.addBindValue(id); //将id值进行绑定

query.exec();

query.next(); //指向第一条记录

qDebug() << id<<"*******"<<query.value(0).toString();

}

运行程序,效果如下:

Qt数据库:(四)利用QSqlQuery类执行SQL语句(二)

我们改变spinBox的数值大小,然后按下“查询”按钮,可以看到对应的结果就出来了。

三,批处理操作。

当要进行多条记录的操作时,我们就可以利用绑定进行批处理。看下面的例子。

#include "widget.h"
#include "ui_widget.h"
#include "connection.h"
#include <QSqlQuery>
#include <QtDebug>
#include <QSqlRecord>
#include <QSqlError>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::on_pushButton_clicked()
{
    QSqlQuery q;
    q.prepare("insert into person values (?,?,?)");
    QVariantList ints;
    ints << 10 << 11 << 12 << 13;
    q.addBindValue(ints);
    QVariantList firstnames;
    firstnames << "xiaoming" << "xiaoliang" << "xiaogang" << QVariant(QVariant::String);
        //最后一个是空字符串,应与前面的格式相同
    q.addBindValue(firstnames);
    QVariantList lastnames;
    lastnames << "laoming" << "laoliang" << "laogang" << QVariant(QVariant::String);
        //最后一个是空字符串,应与前面的格式相同
    q.addBindValue(lastnames);
    if (!q.execBatch()) //进行批处理,如果出错就输出错误
         qDebug() << q.lastError();
        //下面输出整张表
    QSqlQuery query;
    query.exec("select * from person");
    while(query.next())
    {
        int id = query.value(0).toInt();
        QString firstname = query.value(1).toString();
        QString lastname = query.value(2).toString();
        qDebug() << id << firstname << lastname;
    }
}
 

然后在widget.cpp文件中添加头文件 #include <QSqlError>   。

我们在程序中利用列表存储了同一属性的多个值,然后进行了值绑定。最后执行execBatch()函数进行批处理。注意程序中利用QVariant(QVariant::String)来输入空值NULL,因为前面都是QString类型的,所以这里要使用QVariant::String 使格式一致化。

运行效果如下:

Qt数据库:(四)利用QSqlQuery类执行SQL语句(二)

四,事务操作。

事务是数据库的一个重要功能,所谓事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位。在Qt中用transaction()开始一个事务操作,用commit()函数或rollback()函数进行结束。commit()表示提交,即提交事务的所有操作。具体地说就是将事务中所有对数据库的更新写回到数据库,事务正常结束。rollback()表示回滚,即在事务运行的过程中发生了某种故障,事务不能继续进行,系统将事务中对数据库的所有已完成的操作全部撤销,回滚到事务开始时的状态。

如下面的例子:

#include "widget.h"
#include "ui_widget.h"
#include "connection.h"
#include <QSqlQuery>
#include <QtDebug>
#include <QSqlRecord>
#include <QSqlError>
#include <QSqlDriver>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::on_pushButton_clicked()
{
 
    if(QSqlDatabase::database().driver()->hasFeature(QSqlDriver::Transactions))
    {     //先判断该数据库是否支持事务操作
        QSqlQuery query;
        if(QSqlDatabase::database().transaction()) //启动事务操作
        {
                //下面执行各种数据库操作
            query.exec("insert into person values (14,'xiaomeng','laomeng')");
            query.exec("delete from person where id = 1");
                //
            if(!QSqlDatabase::database().commit())
            {
                qDebug() << QSqlDatabase::database().lastError(); //提交
                if(!QSqlDatabase::database().rollback())
                    qDebug() << QSqlDatabase::database().lastError(); //回滚
            }
         }
            //输出整张表
         query.exec("select * from person");
         while(query.next())
         qDebug() << query.value(0).toInt() << query.value(1).toString() <<query.value(2).toString();
     }
}

然后在widget.cpp文件中添加头文件 #include <QSqlDriver> 。

QSqlDatabase::database()返回程序前面所生成的连接的QSqlDatabase对象。hasFeature()函数可以查看一个数据库是否支持事务。

运行结果如下:

Qt数据库:(四)利用QSqlQuery类执行SQL语句(二)

可以看到结果是正确的。

对SQL语句我们就介绍这么多,其实Qt中提供了更为简单的不需要SQL语句就可以操作数据库的方法,我们在下一节讲述这些内容。