Qt SQL:QSqlQuery

一、描述

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

QSqlQuery 封装了在 QSqlDatabase 上执行的 SQL 查询中创建、导航和检索数据所涉及的功能。它可用于执行 DML(数据操作语言)语句,如 SELECTINSERTUPDATEDELETE,以及 DDL(数据定义语言)语句,如 CREATE TABLE。它还可用于执行非标准 SQL 的特定于数据库的命令。

成功执行的 SQL 语句将查询的状态设置为活动(isActive() 返回 true)。

使用以下功能执行导航记录:

  • next()
  • previous()
  • first()
  • last()
  • seek()

这些函数可以在查询返回的记录中向前、向后或任意移动。如果只需要在结果中前进移到,可以使用 setForwardOnly(),这将节省大量内存开销并提高某些数据库的性能。如:

    QSqlQuery query("SELECT country FROM artist");
    while (query.next()) 
    {
        QString country = query.value(0).toString();
        doSomething(country);
    }

使用 value(int) 访问查询返回的数据(从 0 开始)。SELECT 语句返回的数据中的字段是通过传递该字段在语句中的位置来访问的。

必须在创建 QSqlQuery 之前加载 SQL 驱动程序并打开连接。此外,查询存在时连接必须保持打开状态,否则 QSqlQuery 的行为是未定义的。

1.1、绑定值

QSqlQuery 支持将参数值绑定到占位符。

下面展示了使用几种不同绑定方法将值绑定到存储过程的示例。

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();

5、将值绑定到存储过程。下面代码调用名为 AsciiToInt() 的存储过程,通过其 in 参数向其传递一个字符,并将其结果作为 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

二、类型成员

1、enum QSqlQuery::BatchExecutionMode

  • ValuesAsRows:更新多行。将 QVariantList 中的每个条目视为更新下一行的值。
  • ValuesAsColumns:更新单行。将 QVariantList 中的每个条目视为数组类型的单个值。

三、成员函数

1、void addBindValue(const QVariant &val, QSql::ParamType paramType = QSql::In)

将值 val 添加到绑定值列表中。

使用无效的 QVarian绑定 NULL 值。

enum QSql::ParamTypeFlag:此枚举用于指定绑定参数的类型。

  • QSql::In:绑定参数用于将数据放入数据库。
  • QSql::Out:绑定参数用于从数据库接收数据。
  • QSql::InOut:绑定参数用于将数据放入数据库,它将在执行查询时被输出数据覆盖。
  • QSql::Binary:如果想指示正在传输的数据是原始二进制数据,则必须与其他标志进行或运算。

2、int at()

返回查询的当前内部位置。第一条记录位于零位置。

如果位置无效,函数返回 QSql::BeforeFirstRowQSql::AfterLastRow

enum QSql::Location:此枚举类型描述了特殊的 SQL 导航位置:

  • QSql::BeforeFirstRow::在第一条记录之前。
  • QSql::AfterLastRow:最后一条记录之后。

3、void bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType = QSql::In)

将占位符 placeholder 设置为绑定到准备好的语句中的值 val。

在指定占位符名称时必须包含占位符标记(例如)。

      void bindValue(int pos, const QVariant &val, QSql::ParamType paramType = QSql::In)

将位置 pos 的占位符设置为绑定到准备好的语句中的值 val。

4、QVariant boundValue(const QString &placeholder)

返回占位符的值。

      QVariant boundValue(int pos)

返回位置 pos 的占位符的值。

5、QVariantList boundValues()

返回绑定值的列表。列表的顺序是绑定顺序,不管是使用命名绑定还是位置绑定。

    QVariantList list = query.boundValues();
    for (int i = 0; i < list.size(); ++i)
        cout << i << ": " << list.at(i).toString().toUtf8().data() << "\n";

6、void clear()

清除结果集并释放查询对象持有的所有资源。将查询状态设置为非活动。

7、const QSqlDriver * driver()

返回与查询对象关联的数据库驱动程序。

8、bool exec(const QString &query)

执行 query 中的 SQL语句。如果执行成功,则返回 true 并将查询状态设置为活动,否则返回false。

参数字符串必须使用适合被查询的 SQL 数据库的语法。

执行后,查询对象定位在无效记录上,必须先导航到有效记录,然后才能检索数据值(如使用 next())。

调用 exec() 时会重置此查询对象的最后一个错误。

对于 SQLite,query 字符串一次只能包含一条语句。如果给出了多个语句,则返回 false。

//执行SQL语句
std::tuple<bool, QSqlError,QSqlQuery> DBUtil::executeSql(const QString & sqlCommand)
{
    db.transaction();
    QSqlQuery query(db);
    bool executeResult = query.exec(sqlCommand);
    db.commit();
    QSqlError err = query.lastError();
    std::tuple<bool, QSqlError,QSqlQuery> tuple(executeResult,err,query);
    return tuple;
}

      bool exec()

执行先前准备好的 SQL 语句。返回执行是否成功。

9、bool execBatch(QSqlQuery::BatchExecutionMode mode = ValuesAsRows)

批量执行之前准备好的 SQL 语句。返回执行是否成功。

    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(QMetaType::QString);
    q.addBindValue(names);

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

上面的示例插入了四个新行:

1 Harald

2 Boris

3 Trond

4 NULL

列表中 QVariants 的类型不得更改。如不能在 QVariantList 中混合整数和字符串 QVariants

10、QString executedQuery()

返回成功执行的最后一个 SQL 字符串。

11、QString lastQuery()

返回正在使用的当前 SQL 文本。

12、void finish()

将查询对象设置为非活动状态,指示数据库驱动程序在重新执行之前不会从此查询对象中获取更多数据。

通常不需要调用此函数,但如果之后要重新使用查询对象,此函数可用于释放锁或游标等资源。

13、bool first()

检索结果中的第一条记录(如果可用),并将查询定位在检索到的记录上。

如果不成功,则将查询位置设置为无效位置并返回 false。

14、bool isActive()

查询对象是否处于活动状态。活动的 QSqlQuery 是一个已经成功执行但尚未 finish() 的 QSqlQuery。

可以通过调用 finish() 或 clear() 使查询对象不活动。

15、bool isForwardOnly()

是否只能向前滚动结果集。

16、bool isNull(int field)

如果查询未激活、查询未定位在有效记录上、没有 field 字段或该字段内容为空,则返回 true。

      bool isNull(const QString &name)

17、bool isSelect()

当前查询是否 SELECT 语句。

18、bool isValid()

查询对象当前是否位于有效记录上。

19、bool last()

检索结果中的最后一条记录(如果可用),并将查询定位在检索到的记录上。

如果不成功,则将查询位置设置为无效位置并返回 false。

20、QSqlError lastError()

返回有关此查询发生的最后一个错误(如果有)的错误信息。

21、QVariant lastInsertId()

如果数据库支持,则返回最近插入行的对象 ID。如果插入操作多于一行,则行为未定义。

22、bool next()

检索结果中的下一条记录(如果可用),并将查询定位在检索到的记录上。

23、bool nextResult()

丢弃当前结果集并导航到下一个结果(如果可用)。

一些数据库能够为存储过程或 SQL 批处理(包含多个语句的查询字符串)返回多个结果集。如果执行查询后有多个结果集可用,则此函数可用于导航到下一个结果集。

  • 如果有新的结果集可用,此函数将返回 true。查询将重新定位在新结果集中的无效记录上,并且必须先导航到有效记录,然后才能检索数据值。
  • 如果新的结果集不可用,该函数将返回 false 并将查询对象设置为非活动状态。

24、int numRowsAffected()

返回受 SQL 语句查询结果影响的行数,如果无法确定,则返回 -1。

对于 SELECT 语句,该函数返回值是未定义的应改用 size() 。

如果查询未激活,则返回 -1。

25、bool prepare(const QString &query)

配置 SQL 语句查询以供执行。

对于 SQLite,一次只能包含一条语句。如果给出了多个语句,则该函数返回 false。

    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();

26、bool previous()

检索结果中的前一条记录(如果可用),并将查询定位在检索到的记录上。 

27、QSqlRecord record()

返回包含当前查询的字段信息的 QSqlRecord。

要从查询中检索值,应该使用 value(),因为它基于索引的查找速度更快。

在以下示例中,将执行 SELECT * FROM 查询。由于 SELECT 返回的列的顺序可能是随机的,因此使用 QSqlRecord::indexOf() 来获取列的索引。

QSqlQuery q("select * from employees");
QSqlRecord rec = q.record();

qDebug() << "Number of columns: " << rec.count();

int nameCol = rec.indexOf("name"); // index of the field "name"
while (q.next())
    qDebug() << q.value(nameCol).toString();

28、const QSqlResult * result()

返回与查询关联的结果。

29、bool seek(int index, bool relative = false)

检索位置 index 处的记录(如果可用),并将查询对象定位在检索到的记录上。第一条记录位于位置 0。

30、void setForwardOnly(bool forward)

设置是否仅向前模式。默认为关闭。

如果 forward 为 true,则仅允许具有正值的 next() 和 seek() 导航结果。

此模式可以(取决于驱动程序)更节省内存,因为不需要缓存结果。

此设置是对数据库引擎的建议。isForwardOnly() 将始终返回结果集的正确状态。

31、void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)

设置查询使用的数值精度策略。

不支持获取低精度数值的驱动程序将忽略精度策略。可以使用 QSqlDriver::hasFeature() 来确定驱动程序是否支持此功能。

32、int size()

返回结果的数目,如果无法确定数目或数据库不支持报告有关查询结果的数目的信息,则返回 -1。

对于非 SELECT 语句(isSelect() 返回 false),size() 将返回 -1。

对于 SELECT 语句应使用 numRowsAffected()。

33、QVariant value(int index)

返回当前记录中字段索引的值。

字段使用 SELECT 语句的文本从左到右编号,如:

SELECT forename, surname FROM people;

字段 0 是 forename,字段 1 是 surname。

不建议使用 SELECT *,因为查询中字段的顺序未定义。

      QVariant value(const QString &name)

返回当前记录中名为 name 的字段的值。

  • 14
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt是一个跨平台的C++应用程序开发框架,它提供了丰富的功能和工具来简化应用程序的开发过程。在Qt中,可以使用QSqlQuery类来创建和操作数据库。 QSqlQuery类是Qt提供的用于执行SQL语句的类,它可以执行查询、插入、更新和删除等操作。下面是使用QSqlQuery类创建数据库的一般步骤: 1. 首先,需要在Qt项目中添加数据库模块的支持。可以在项目文件(.pro)中添加如下代码: ``` QT += sql ``` 2. 在代码中包含QSqlQuery头文件: ``` #include <QSqlQuery> ``` 3. 创建数据库连接: ``` QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("database.db"); // 设置数据库名称 if (!db.open()) { // 处理数据库连接失败的情况 } ``` 4. 执行SQL语句: ``` QSqlQuery query; query.exec("CREATE TABLE IF NOT EXISTS students (id INT PRIMARY KEY, name TEXT, age INT)"); ``` 上述代码创建了一个名为"students"的表,包含id、name和age三个字段。 5. 可以通过QSqlQuery的其他方法来执行不同的SQL操作,例如插入数据、查询数据等。例如,插入一条数据: ``` query.prepare("INSERT INTO students (id, name, age) VALUES (:id, :name, :age)"); query.bindValue(":id", 1); query.bindValue(":name", "John"); query.bindValue(":age", 20); query.exec(); ``` 上述代码将一条id为1、name为"John"、age为20的记录插入到"students"表中。 6. 最后,记得在不需要使用数据库时关闭数据库连接: ``` db.close(); ``` 以上是使用QSqlQuery类创建数据库的基本步骤。你可以根据具体需求使用QSqlQuery的其他方法来执行更复杂的数据库操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值