0、说明

QSqlQuery提供了执行SQL代码的方法。

QSqlQuery封装了在QSqlDatabase中查询、检索数据的相关函数。它可以用来执行如SELECT、INSERT、UPDATE、DELETE等方法,也可以执行如CREATE TABLE等语句。

顺利执行SQL语句后,调用isActive()就会返回true。一个激活的Query一定会产生一个合法的记录(isValid()返回true),从这个记录中可以提取到需要的数据。

对某些数据库而言,如果有一个诸如SELECT的Query是激活状态,那么当我们调用commit()、rollback()时,相关事务操作会失败。

历史查询记录可以通过如下函数进行查询:

next()、previous()、first()、last()、seek()

这些函数允许编辑器随意浏览上一个、下一个、任意一个查询记录。如果我们只需要往后查看结果(调用next()),那么可以调用setForwardOnly(),这样相比随机存储就可以存储大量信息,并且提高查询效率。

一旦一个激活的Query返回了一个合法记录,可以通过value()来提取其中的数据。所有SQL查询到的数据都是QVariant类型。

Query成功后,每个Query都是一条记录(即一行),可以用while(query.next())来实现查询每行的目的,每条记录有多少个value是与SELECT语句中的查询项数相关的,通过value(i)查询对应的项,每次查询到的值都是QVariant类型,通过QVariant的toT()方法转换为对应的类型(这里T是泛型而不是实际类型),具体见QVaraint官方文档

例如:

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

为了访问Query得到的数据,可以使用value( int )方法。Query的结果数据中,索引是从0开始的,因此调用SELECT *进行查询是不可用的,因为返回顺序是不确定的。

为了提高效率,不存在通过name访问数据的方法(除非预先在SELECT语句中通过names进行查询)。为了将数据name转换为索引,需要使用record().indexOf(),例如:

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

调用numRowsAffected()可以知道有多少行是被非SELECT查询影响,调用size()可以知道有多少行是被SELECT查询影响的。

需要注意的是,在创建QSqlQuery之前,必须先加载SQL Driver并且构建连接。此外,当Query存在时,连接必须维持open状态,否则QSqlQuery的行为将不会执行。

预定义查询与带占位符的查询

预定义查询:事先定义好查询语句,但暂时并不执行,通常是因为其中的项没有设置,通常与占位符结合使用;

什么是带占位符的查询呢?就是在查询语句中,并不把语句写完整,而是某些地方填入占位符后,之后把占位符补充完整,就构成了一个完整的查询。就像下边这样:

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

几种占位符查询的方式:

①name占位符与name填充

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

②name占位符与pos填充

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

③?占位符与pos填充

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

④?占位符与顺序填充

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

1、模块和载入项

Header: #include <QSqlQuery>
qmake: QT += sql

2、构造

QSqlQuery(QSqlQuery other) 构造一个Query的副本
QSqlQuery(QSqlDatabase db) 在db上构造一个Query,如果db不存在则用默认db
QSqlQuery(QString query = QString(), QSqlDatabase db = QSqlDatabase())

用query和db构造一个Query,其中query是SQL语句对应的字符串

如果db为空或者非法,会使用默认db,如果query非空,那么在构造之后它会被执行

QSqlQuery(QSqlResult *result) 用某个查询结果QSqlResult构造一个QSqlQuery

3、静态字段

类型

字段

取值

说明

enum BatchExecutionMode { ValuesAsRows, ValuesAsColumns }  
Constant Value Description
QSqlQuery::ValuesAsRows 0 - Updates multiple rows. Treats every entry in a QVariantList as a value for updating the next row.
QSqlQuery::ValuesAsColumns 1 - Updates a single row. Treats every entry in a QVariantList as a single value of an array type.

4、成员方法

返回值类型

方法

说明

QSqlQuery & operator=(QSqlQuery other) 赋值
void addBindValue(QVariant val, QSql::ParamType paramType = QSql::In) 用于第四种情况的?占位符
int at()

返回当前查询到的记录的索引,第一个记录的索引为0

失败时返回一个负数

void

bindValue(QString placeholder, QVariant val, QSql::ParamType paramType = QSql::In)

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

①、②、③中占位符,第一个参数是占位符,第二个参数是它的值

QVariant

QVariant

QMap<QString, QVariant>

boundValue(QString placeholder)

boundValue(int pos)

boundValues()

返回占位符对应的值

返回占位符及其值构成的QMap<QString , QVariant>

void clear() 清除result集合,释放该Query占有的资源。设置Query状态为非激活,我们几乎不需要调用该方法。
QSqlDriver * driver() 该Query相关的driver
bool

exec(QString query)

参数是一个SQL Query语句执行该语句。

Query成功时返回true,并设置query为激活状态。

当Query执行后,需要不断调用next()来让该Query定位到一个合法的记录处,之后才能提取数据。

当调用exec()时,该Query的last error将被重置。

例子:

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

exec()

执行用prepare()预定义的查询语句,成功时返回true。

执行时会重置该query的last error。

bool execBatch(QSqlQuery::BatchExecutionMode mode = ValuesAsRows)
QString executedQuery()

返回上一次成功执行的Query String。

如果是带占位符的预定义查询,会在占位符处填充真实值。

void finish()

告诉Driver不需要再从Query中查询数据了。

通常不需要调用该方法,但是在重用该Query前调用该方法会释放资源以保证资源安全。

设置Query为非激活状态,占位符绑定的值将会维持不变。

bool first()

提取Query结果的第一条记录,并将Query定位到该条记录上。

Query结果必须是激活状态,并且isSelect()必须返回true,之后才能调用该方法,否则将会返回false并不做任何事情。

bool isActive()

如果Query是激活状态则返回true。激活的Query是指成功调用了exec()并且没有调用finish()之前的Query。

完成查询之后,可以通过finish()或clear()修改Query为非激活状态,或者也能直接删除该QSqlQuery实例。

在提交、回滚事务之前,必须用以上方法来使Query变为非激活状态。

bool isForwardOnly() 如果只能在结果集中向前单向查询,返回true。
bool

isNull(int field)

isNull(QString name)

以下几种情况返回true:1、Query未激活;2、Query未定位到一个合法记录上;3、结果上没有指定field;4、field是null。
bool isSelect() 如果当前Query是SELECT语句返回true
bool isValid() 如果当前Query定位到一个合法记录上,返回true
bool last() 定位当前Query到最后一条记录上。
QSqlError lastError() 返回该Query最近的错误信息
QVariant lastInsertId()

返回最近插入行对应的object ID。

失败时返回一个非法的QVariant。

如果一次插入了多行,结果将是Undefined。

QString lastQuery() 返回上一次查询语句,如果没有则返回空String。
bool next()

定位到查询结果的下一条记录上。

以下规则将会应用:

①如果当前定位到第一条记录之前——常用于执行后立即查询,那么结果会使Query定位到第一条记录;

②如果定位到最后一条记录,那么什么都不做并返回false;

③如果定位到中间,则定位到下一条记录。

bool nextResult() 删除当前记录并定位到下一条记录上。
int numRowsAffected()

返回SQL语句将会影响的行数,不确定时返回-1。

如果是SELECT语句,不能用该方法,应该用size()。

Query未激活时返回-1。

QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() 返回当前的数字精度策略。 
bool prepare(QString query) 预定义查询。
bool previous() 定位当前Query为上一条记录。
QSqlRecord record()

返回当前Query的结果QSqlRecord,其中包含了Query结果的字段信息。

如果Query指向一个合法的行,那么QSqlRecord将用指定行值填充,当Query未激活时,会返回一个空的记录。

为了从Query中提取值,调用基于索引的value()进行检索将会速度更快。

下边的例子中,使用了SELECT * FROM查询语句。由于结果列的顺序并不确定,所以通过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(); // output all names
QSqlResult * result() 返回该Query的Result
bool seek(int index, bool relative = false) 定位到指定记录处,第二个参数指定相对、绝对偏移,即以当前位置为基准还是以开头为基准。
void setForwardOnly(bool forward)

只允许前向查询。当forward为true时,next()、seek()方法只能用正数。

这个方法应当在Query exec前主动调用,默认情况下前向查询是未激活的。

void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy) 设置数值精度
int size()

返回查询结果的size,即行数。失败时返回-1。

非SELECT语句会返回-1,应该调用numRowsAffected()。

QVariant

value(int index)

value(QString name)

返回当前记录中,索引字段index的值,一个字段就是一列,索引从0开始。不推荐使用SELECT *因为字段顺序会被打乱。失败时返回一个非法QVariant。

用列名的方式访问当前记录中某个字段的值。

7、用法

1)在某个已经open的QSqlDatabase连接上构造QSqlQuery对象,方便后续查询:

QSqlQuery query(db);//db是QSqlDatabase且已经Open

2)构造SQL语句QString,进行查询:

    QSqlQuery query(db);
QString sql = "SELECT str.id,str.imei,str.table_name,";
sql+="sed.location_x,sed.location_y ";
sql+="FROM sensor_table_relation str , sensor_end_data sed ";
sql+="WHERE str.imei = sed.imei ";
sql+="ORDER BY str.id";
query.exec(sql);

3)看看一共查询到了多少项:

如果用SELECT 列名1,列名2,...查询,用size()

如果用SELECT *查询,应当用numRowsAffected()

    qDebug()<<query.size();//68

4)不断地提取某条记录的所有字段:

在上文中,我们SELECT了5项:

  • str.id
  • str.imei
  • str.table_name
  • sed.location_x
  • sed.location_y

可以用value(i)的方式提取每条记录中的每项,一共5项,那么i的取值就为0~4,跟这5项一一对应。需要注意的是value(i)提取的项是QVariant类型,要用toT()转化为指定的Qt类型。

不断地调用next(),可以依次将QSqlQuery定位到下一条记录上,结合value(i),就能实现提取所有查找记录的所有项的功能:

while(query.next()){
QString imei = query.value(1).toString();
QString table_name = query.value(2).toString();
float locationX = query.value(3).toFloat();
float locationY = query.value(4).toFloat(); Info info( imei , table_name , locationX , locationY);//自定义存储查询结果的类,类似于Java中的ORM机制
infolist.append(info);//把所有记录存入一个QList<Info>中
}

 注意:查询完毕后,query并没有指向返回的第一条记录处,需要先调用next()才能正确访问第一条记录的各项(这点十分重要)。

Qt:QSqlQuery的更多相关文章

  1. Qt:禁止qDebug的输出

    Qt:禁止qDebug的输出 在工程的.pro文件里加上以下编译批令即可: DEFINES += QT_NO_DEBUG_OUTPUT

  2. Qt:使用自定义的字体

    Qt:使用自定义的字体 1. 下载字体文件 2. 加载字体文件 3. 使用字体   QFontDatabase::addApplicationFont("XENOTRON.TTF" ...

  3. Qt:QJsonObject

    0.说明 QJsonObject在逻辑上就是一个Map或Dict!记住这一点对理解它的方法.说明很有帮助. QJsonObject类封装了JSON Object. JSON Object是一个Key- ...

  4. Qt:QJsonValue

    0.说明 QJsonValue类用于操作JSON中的各种数据. JSON是用于存储结构化数据的格式,JSON中的数据可以是六种类型: 基本类型 存储类型 bool QJsonValue::Bool d ...

  5. Qt:QJsonArray

    0.说明 QJsonArray中存储了一系列的QJsonValue.可以向其中插入.删除QJsonValue. 一个QJsonArray可以与QVariantList互相转换.可以通过size()访问 ...

  6. Qt:QUrl构造时的qrc前缀

    参考(按对我帮助从大到小排列): Qt内的各种路径(让人迷惑) - 鬼谷子com - 博客园 qt webengineview 加载本地资源方式 - beautifulday - 博客园 (17条消息 ...

  7. Qt:QSqlDatabase

    0.说明 QSqlDatabase类处理与数据库连接相关的操作.一个QSqlDatabase实例就代表了一个连接,连接时要提供访问数据库的driver,driver继承自QSqlDriver. 通过静 ...

  8. Qt:正则表达式语法:

         正则表达式是验证输入.从输入中提取数据以及对输入进行搜索和替换的强大工具,所谓正则表达式,regexp是一种利用模式匹配语言来描述字符串组成限制条件的方式;        Qt 提供了一个Q ...

  9. Qt:QT右键菜单

    Qt QTableView 上加右键弹出菜单, 并复制选中的单元格内容到剪贴板中 http://wenku.baidu.com/view/c51cfb63cf84b9d528ea7a29.html h ...

随机推荐

  1. Clusternet:一款开源的跨云多集群云原生管控利器!

    作者 徐迪,Clusternet 项目发起人,腾讯云容器技术专家. 摘要 Clusternet (Cluster Internet)是一个兼具多集群管理和跨集群应用编排的开源云原生管控平台,解决了跨云 ...

  2. Android开发之打包apk

    新建一个项目之后写点代码 选择build 之后选择Generate Signed APK (生成签名的APK) 选择create new 填写信息 Generate Signed APK 生成签名的A ...

  3. 面向次世代的Windows App SDK 近况

    Project Reunion作为面向次世代Windows App Development的统一工具集.在2021年11月,第三个稳定版正式以1.0的版本号发布的同时,改名部果断出手,以全新的名称Wi ...

  4. 右键没有word?excel?ppt?注解表该改改啦

    ✿[office 2019]office2010版本以上的都可以(例如:office 2010.office 2016.office 2019) 一.快速方法解决右键没有word: 在电脑桌面右键一个 ...

  5. 正向代理 、反向代理, 和 Linux系统配置nginx。

    一.正向代理和反向代理的简单介绍. 2.代理 中间商,赚差价 在没有代理的时候: 茅台酒厂--->生产了一批酒--->通过物流发送到客户的家中/客户直接到酒厂购买酒--->突然有一个 ...

  6. halcon视觉入门钢珠识别

    halcon视觉入门钢珠识别 经过入门篇,我们有了基础的视觉识别知识.现在加以应用. 有如下图片: 我们需要识别图片中比较明亮的中间区域,有黑色的钢珠,我们需要知道他的位置和面积. 分析如何识别 编写 ...

  7. UIFont

    UIFont代表字体,常见创建方法有以下几个:+ (UIFont *)systemFontOfSize:(CGFloat)fontSize; 系统默认字体+ (UIFont *)boldSystemF ...

  8. redis集群升级,数据迁移及校验

    本次由于安全漏洞原因,需要降redis3升级为redis6,涉及到数据迁移及校验等,用阿里redis-shake迁移工具迁移,并用阿里RedisFullCheck工具进行数据比对 一.新redis安装 ...

  9. Docker容器之搭建本地私有仓库

    Docker容器之搭建本地私有仓库 本地私有仓库搭建的具体步骤 首先下载 registry 镜像 docker pull registry 在 daemon.json 文件中添加私有镜像仓库的地址并重 ...

  10. 解决/WEB-INF目录下的jsp页面引入webRoot下的Js、css和图片的问题

    通常把jsp页面放在webRoot的/WEB-INF下可以防止访问者直接输入页面. 而webRoot的/WEB-INF下的页面是受保护的,用户无法通过形如http://localhost:8080/t ...