Qt 之 QSqlQuery Class

32 篇文章 1 订阅
31 篇文章 2 订阅

详细描述

QSqlQuery 类提供了一种执行和操作SQL语句的方法。

QSqlQuery 封装了从在一个 QSqlDatabase(数据库连接)上的SQL 查询(queries) 创建,导航,检索(取回) 数据的功能。它可以用来执行DML(data manipulation language)即数据操作语句,比如 select,insert,update,delete 即数据库最常用的增删改查操作语句,也可以用来执行DDL(data definition language)即数据定义语句,例如 create table。它同样可以用来执行不属于国际标准SQL的特定数据库的命令(例如,PostgreSQL的 SET DATESTYLE=ISO)。


成功执行SQL语句会设置query的状态为活跃(active),isActive()  返回true。否则query的状态被设置为不活跃(inactive)。不论哪种情况,当执行一条新的SQL语句时,查询(query) 定位在一条无效的记录上。一个活跃的query查询在值可以被检索到之前必须被导航到一条有效的记录(因此isValid()返回true)。


对于一些数据库,当你调用 commit() 或者 rollback() 时如果一个活跃的查询(query)存在select语句,那么commit(事务)或者rollback(回滚)将会失败。


可以通过以下函数去访问查询到的数据库记录:next()previous()first()last()seek()。这些函数允许程序员向前,向后或者任意地访问query返回的记录。如果你只需要向前访问结果集(比如使用next()),你可以使用 setForwardOnly() ,这将节省大量的内存开销并提高某些数据库的性能。一旦一个活跃的查询被定位在一条有效的记录上,可以通过value()函数检索数据。所有数据都是使用QVariants数据类型从SQL 后台传输的。

举个例子:

   //查询之前记得先打开数据库连接。。。
   QSqlQuery query("SELECT country FROM artist");
    while (query.next()) {
        QString country = query.value(0).toString();
        doSomething(country);
    }

使用value(int)可以访问到query对象返回的数据。 由SELECT语句返回的数据中的每个字段都是通过在语句中传递字段的位置来访问的,从0开始。这使得使用SELECT *查询是不明智的,因为返回的字段的顺序是不确定的。

出于效率考虑,没有通过字段名访问字段内容的函数,除非你使用带名字的prepared queries(可是明明有QVariant QSqlQuery::value(const QString & name) const,。可能这个重载函数是在后面加入的,而当前的文档是还没加入这个重载函数的时候写的),使用record().indexOf()可以将一个字段名转换成对应的索引,例如:

    QSqlQuery query("SELECT * FROM artist");
    int fieldNo = query.record().indexOf("country");
    while (query.next()) {
        QString country = query.value(fieldNo).toString();
        doSomething(country);
    }

QSqlQuery支持准备查询执行(prepared query execution)和将参数值绑定到占位符。一些数据库不支持这些特性,对于那些不支持的,Qt模拟了所需的功能。例如,Oracle和ODBC支持准备查询(prepared query),Qt使用支持的这种特性;但对于不支持这种特性的数据库,Qt自己实现了这些特性,比如说,当执行一条查询通过实际值去代替占位符。使用numRowsAffected() 找出多少条非查询(non-SELECT)查询生效,使用size()去找出由SELECT查找出的数量。


Oracle数据库通过 ‘冒号字段名’  来识别占位符,例如 :‘:name’.ODBC简单地使用了 ? 字符。这两种语法Qt都支持,限制条件是你不能在同一个查询中混合使用这两种语法。

你可以使用QMap<QString, QVariant> QSqlQuery::boundValues() const检索在单个变量(映射 )中所有字段的值。例如:

    QMapIterator<QString, QVariant> i(query.boundValues());
    while (i.hasNext()) {
        i.next();
        cout << i.key().toUtf8().data() << ": "
             << i.value().toString().toUtf8().data() << endl;
    }
等价于:

    QList<QVariant> list = query.boundValues().values();
    for (int i = 0; i < list.size(); ++i)
        cout << i << ": " << list.at(i).toString().toUtf8().data() << endl;

绑定值的几种方法

下面,我们将使用四种不同的绑定方法,每一种方法给出相同的示例,以及将值绑定到存储过程的一个示例。

1、使用命名占位符命名的绑定:

    QSqlQuery query;
    query.prepare("INSERT INTO person (id, forename, surname) "
                  "VALUES (:id, :forename, :surname)");
    query.bindValue(":id", 1001);
    query.bindValue(":forename", "Bart");
    query.bindValue(":surname", "Simpson");
    query.exec();

2、使用指定占位符的位置绑定:

    QSqlQuery query;
    query.prepare("INSERT INTO person (id, forename, surname) "
                  "VALUES (:id, :forename, :surname)");
    query.bindValue(0, 1001);
    query.bindValue(1, "Bart");
    query.bindValue(2, "Simpson");
    query.exec();
3、使用位置占位符绑定值(版本1):
    QSqlQuery query;
    query.prepare("INSERT INTO person (id, forename, surname) "
                  "VALUES (?, ?, ?)");
    query.bindValue(0, 1001);
    query.bindValue(1, "Bart");
    query.bindValue(2, "Simpson");
    query.exec();

4、使用位置占位符的绑定值(版本2):
 
    QSqlQuery query;
    query.prepare("INSERT INTO person (id, forename, surname) "
                  "VALUES (?, ?, ?)");
    query.addBindValue(1001);
    query.addBindValue("Bart");
    query.addBindValue("Simpson");
    query.exec();

将值绑定到存储过程(procedure):

这段代码调用了一个名叫AsciiToInt()的存储过程,通过参数传递一个字符,并将其结果输出到out参数中。

    QSqlQuery query;
    query.prepare("CALL AsciiToInt(?, ?)");
    query.bindValue(0, "A");
    query.bindValue(1, 0, QSql::Out);
    query.exec();
    int i = query.boundValue(1).toInt(); // i is 65

注意,未绑定的参数将保留它们的值。

使用return语句返回值或返回多个结果集的存储过程没有得到完全的支持。具体细节请参见 SQL Database Drivers(可到Qt Assistant中检索关键字)。
警告:你必须在一个QSqlQuery创建之前加载SQL驱动和打开数据库连接(QSqlDatabase).并且,在QSqlQuery对象存在是数据库连接一定要保持打开;否则,QSqlQuery的行为是未定义的。

API介绍

bool QSqlQuery::execBatch(BatchExecutionMode mode = ValuesAsRows)
在批处理中执行提前准备好的SQL查询,所有的绑定参数都必须是QVariant的链表。如果数据库不支持批处理,则驱动程序将使用常规exec()调用来模拟它。查询成功执行返回true;否则返回false。
例子:
QSqlQuery q;
q.prepare("insert into myTable values (?, ?)");

QVariantList ints;
ints << 1 << 2 << 3 << 4;
q.addBindValue(ints);

QVariantList names;
names << "Harald" << "Boris" << "Trond" << QVariant(QVariant::String);
q.addBindValue(names);

if (!q.execBatch())
    qDebug() << q.lastError();

上面的例子在myTable表中插入了4个新行:
1  Harald
2  Boris
3  Trond
4  NULL

要绑定NULL值,必须将相关类型的空QVariant添加到绑定的QVariantList中;比如,如果你使用strings(字符串)QVariant(QVariant::String)应该被添加到QVariantList中。
注意:每个绑定的QVariantList必须包含相同数量的变体。
注意:列表中的QVariant的类型不能改变。例如,您不能在QVariantList中混合整数和字符串变体。



                
要使用qt中的QSqlQuery类,首先需要在.pro文件中添加以下代码:QT += sql。这样可以确保qt能够正常使用QtSql模块的功能。 在编译运行后,可以看到已经创建了该文件。创建成功后,该文件默认为空,然后就可以使用QSqlQuery类来操作该数据库。QSqlQuery类使用的是SQL语句来进行数据库操作。如果只需要使用高层次的数据库接口而不关心SQL语法,可以选择使用QSqlTableModel和QSqlRelationalTableModel(在后续章节介绍)。在本章中,我们将介绍如何使用QSqlQuery类进行SQL语法操作。 需要注意的是,QSqlDatabase类提供了一个接口,用于通过连接访问数据。QSqlDatabase的一个实例表示一个连接,这个连接通过受支持的数据库驱动程序之一提供对数据库的访问,该驱动程序派生自QSqlDriver。在创建一个数据库的示例中,我们需要使用QSqlDatabase类创建一个连接,并设置数据库的名称。如果在当前目录下没有该文件,会在该目录下生成一个新的数据库文件。如果该文件已经存在,则会连接到该文件。如果数据库连接失败,可以通过QMessageBox进行错误提示。 总结起来,要使用qt的QSqlQuery类,需要在.pro文件中添加相应代码,然后创建一个QSqlDatabase对象并设置数据库名称,最后使用QSqlQuery对象进行SQL语法操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [QT-QSqlQuery类操作SQLite数据库(创建、查询、删除、修改)详解](https://blog.csdn.net/qq_45809384/article/details/131189328)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值