Qt SQL:QSqlQuery

Posted 友善啊,朋友

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 的字段的值。

Qt数据库- 执行SQL语句

技术图片

Qt Version 5.14.0

QSqlQuery类提供执行SQL语句的接口,并且能够访问执行结果数据集。

执行一次查询

想要执行SQL语句,只需要创建一个QSqlQuery对象,然后调用它的exec函数,如下代码。(这里构造QSqlQuery对象时没有指定数据库链接名称)

QSqlQuery  query;
bool  flag  =  query.exec("SELECT  name,  salary  FROM  employee  WHERE  salary  >  50000");
if(false  ==  flag)
{
  qDebug()  <<  query.lastError();
}

访问结果数据集

QSqlQuery提供的接口每次只能访问结果集中的一条记录,在执行完exec()函数后,QSqlQuery对象的内部指针位于结果集第一条数据之前,调用next()函数访问第一条结果集,然后再不断调用next()函数访问剩余所有数据,示例代码如下:

while (query.next()) {
 QString name = query.value(0).toString();
 int salary = query.value(1).toInt();
 qDebug() << name << salary;
 }

QSqlQuery::value()函数用于从一条记录中读取某个特定字段的数据。字段由索引指定(从0开始),value()函数的返回值是QVariant类型的,这个类型可以保存所有C++和Qt Core中定义的类型。不同数据库的数据类型会自动映射到Qt支持的对应类型,之后可以调用toInt()、toString()等函数将其转换为具体的数据。Qt具体支持的各个数据库的数据类型,详见Qt助手关键词: Data Types for Qt-supported Database Systems。

访问结果数据集可以使用的QSqlQuery接口有:

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

当前位置的索引可以通过at()获取,结果集总行数使用size()函数获取(如果该数据库支持此接口)。

一个数据库驱动是否支持某个特性该如何判断,可以使用hasFeature()函数。

在你浏览结果集数据时,如果只使用next()和seek()函数,则可以在调用exec()之前,调用setForwardOnly(true)来提高效率。

插入、更新和删除

QSqlQuery::exec()可以执行任意SQL语句,如果你想一次插入很多条数据,可以使用占位符来提高效率(这样可以自动将各个数据类型转换为QString类型,简化SQL语句字符串的构建过程)。

Qt支持两种类型的占位符:名字绑定 和 位置绑定

名字绑定示例代码如下:

 QSqlQuery query;
 query.prepare("INSERT INTO employee (id, name, salary) "
 		"VALUES (:id, :name, :salary)");
 query.bindValue(":id", 1001);
 query.bindValue(":name", "Thad Beaumont");
 query.bindValue(":salary", 65000);
 query.exec();

位置绑定示例代码如下:

 QSqlQuery query;
 query.prepare("INSERT INTO employee (id, name, salary) "
 "VALUES (?, ?, ?)");
 query.addBindValue(1001);
 query.addBindValue("Thad Beaumont");
 query.addBindValue(65000);
 query.exec();

Qt提供的所有数据库驱动都支持这两种绑定方式。如果数据库原生支持这种句法,Qt会直接将这个query传给DBMS,否则会对其进行预处理。实际执行的query可以调用executedQuery()来获得。

更新和删除类似。

事务

事务可以保证一个复杂的操作是原子的,即要么都执行,要么都不执行。 如果数据库支持事务,QSqlDriver::hasFeature(QSqlDriver::Transactions)会返回true。

使用事务的步骤如下:

  • 初始化事务( QSqlDatabase::transaction())
  • 执行query
  • 执行成功则提交事务(commit()),执行失败则回滚(rollback())

 

 

 

 

 

 

 

============================================================================================================

 

qt之QSqlQuery

QSqlQuery提供了一个执行和查询的状态,该类封装了函数提取和检索数据的功能,它可以被用做数据操作

语句,列出select insert update selete ,也介意作为数据定义语句,列如create table

 

成功执行sql语句 isActive会返回true,否则返回false,

 

通过导出记录执行以下语句

   

   

· next()

· previous()

· first()

· last()

· seek()

  游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制

  这些函数允许程序设计者去向前向后移动在记录中

 

   For example:

 

      QSqlQuery query("SELECT country FROM artist");

      while (query.next()) {

          QString country = query.value(0).toString();

          doSomething(country);

      }

参数化查询

    

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

 

    QSqlQuery query;

      query.prepare("INSERT INTO person (id, forename, surname) "

                    "VALUES (?, ?, ?)");

      query.addBindValue(1001);

      query.addBindValue("Bart");

      query.addBindValue("Simpson");

      query.exec();

 

QSqlQuery::QSqlQuery(QSqlResult *result)

根据结果集构造一个QSqlQuery对象

QSqlQuery::QSqlQuery(QSqlDatabase db)

根据数据库得到一个QSqlQuery对象

void QSqlQuery::addBindValue(const QVariant &valQSql::ParamType paramType = QSql::In)

 参数化查询的时候,调用该函数,

int QSqlQuery::at() const

 返回当前内部查询的位置,该位置是以0开始。

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

      构建参数。

     void QSqlQuery::clear()

      清除结果集,并释放资源

     bool QSqlQuery::exec(const QString &query)

执行查询

  bool QSqlQuery::exec()

 执行一个已经准备好的查询。

QString QSqlQuery::executedQuery() const

返回最后一次查询的字符串。

int QSqlQuery::numRowsAffected() const

返回影响的函数

bool QSqlQuery::prepare(const QString &query)

构建准备查询语句

bool QSqlQuery::previous()

在结构集中返回上一个结果集。

const QSqlResult *QSqlQuery::result() const

 

 返回结果集

void QSqlQuery::setForwardOnly(bool forward)

设置向前查询

int QSqlQuery::size() const

返回结果集的大小

QVariant QSqlQuery::value(int index) const

返回值

QVariant QSqlQuery::value(const QString &name) const

根据字段名返回值。

 

 

============================================================================================================

以上是关于Qt SQL:QSqlQuery的主要内容,如果未能解决你的问题,请参考以下文章

QSqlDatabasePrivate::addDatabase: 重复的连接名称 'qt_sql_default_connection'

QT之SQL的使用

Qt4:将 SQL 表打印为 PDF

[QT][SQL]sql学习记录3_sqlite 使用

Qt SQL Programming 部分翻译

Qt SQL:QSqlQuery