QSqlQuery类提供了一个用于执行SQL语句和浏览查询的结果集的接口。数据库
QSqlQueryModel和QSqlTableModel类提供了一个用于访问数据库的高级接口,这将在下一节介绍。若是你不熟悉SQL,你能够直接使用下一节介绍的高级接口类。app
1 执行一个查询函数
要执行一个SQL语句,简单的建立一个QSqlQuery对象,而后调用QSqlQuery::exec()方法便可,以下所示:性能
QSqlQuery query; query.exec("SELECT name, salary FROM employee WHERE salary > 50000");
QSqlQuery的构造函数接受一个可选的QSqlDatabase对象参数,用来指定将使用哪个数据库链接。在上面的例子中,咱们并无指定任何链接,所以使用默认链接。若是执行查询时出错,exec()将返回false,错误缘由能够经过QSqlQuery::lastError()查看。优化
2 浏览查询结果ui
QSqlQuery提供了一个访问一条查询结果记录的方法。在调用了exec()方法以后,QSqlQuery的内部指针定位到了第一条记录以前的位置。咱们必须调用一次QSqlQuery::next()内部指针就移动到第一条记录上,而后重复调用next()方法就能够移动到其余记录上,直到该函数返回false为止。下面给出一个典型的循环依次遍历全部的记录:this
while (query.next()) { QString name = query.value(0).toString(); int salary = query.value(1).toInt(); qDebug() << name << salary; }
QSqlQuery::value()函数返回当前记录的一个字段值。字段的索引号从0开始计数。QSqlQuery::value()返回一个QVariant,这个类型能够保存各类C++和核心的Qt数据类型,好比int, QString和QByteArray等。不一样的数据库类型将自动地映射到最近的Qt等价类型。在上面的代码中,咱们使用了QVariant::toString()和QVariant::toInt()将变量类型转换为了QString和int。spa
补充:关于value()方法的参数-索引号的取值范围问题,咱们只知道第一个字段对应的索引号为0,可是并不知道最后一个字段的索引号的时候,咱们能够遍历全部可能值,因为当value()函数的索引号非法时,会返回一个非法的QVariant变量,所以,咱们能够经过判断返回的QVariant变量的合法性来得知是否已经到了最后一个字段。下面给出一段示例代码:指针
while (query.next()){ int i = 0; QString result; QVariant temp; while ((temp = query.value(i++)).isValid()){ result += temp.toString(); result += " | "; } ui->textBrowser->append(result); }
下面给出一个MYSQL与Qt支持的数据类型之间的转换关系表:code
SQLITE3与Qt支持的数据类型之间的转换关系表以下:
你可使用QSqlQuery::next(),QSqlQuery::previous(), QSqlQuery::first()和QSqlQuery::last()来先后移动指向记录位置的指针。可使用QSqlQuery::at()返回当前行的索引号,若是对应的数据库支持,可使用QSqlQuery::size()返回查询结果集的总的行数(MYSQL是支持的)。
要验证一个数据库驱动是否支持某一个特性,QSqlDriver::hasFeature()。下面的示例咱们调用调用QSqlQuery::size()来检查底层的数据库是否支持此特性,不然,咱们只能浏览到最后一条记录,利用查询的位置来获得查询结果中一共有多少条记录。
QSqlQuery query; int numRows; query.exec("SELECT name, salary FROM employee WHERE salary > 50000"); QSqlDatabase defaultDB = QSqlDatabase::database(); if (defaultDB.driver()->hasFeature(QSqlDriver::QuerySize)) { numRows = query.size(); } else { // this can be very slow query.last(); numRows = query.at() + 1; }
若是你在遍历查询结果集的时候只使用正值参数的next()和seek(),你能够在调用exec()以前调用QSqlQuery::setForwartOnly(true)。当你在操做大量结果集的时候,这是一个简单的优化单能够明显加速你的查询。
3 插入、更新和删除记录
QSqlQuery能够执行任意的SQL语句。下面的示例展现了使用INSERT语句向表中插入一条记录:
QSqlQuery query; query.exec("INSERT INTO employee (id, name, salary) " "VALUES (1001, 'Thad Beaumont', 65000)");
若是你想要同时插入许多条记录,一个有效的方法就是将查询语句和真实的值分离,这个可使用占位符来实现。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提供的全部数据库驱动都支持。当须要插入多条记录时,只须要调用 一次QSqlQuery::prepare(),而后使用屡次bindValue()或者addBindValue()来绑定须要的数据,最后再调用一次exec()函数就能够了。
抛开性能,使用占位符的一个好处就是你能够指定任意的值而不用担忧缺乏特殊字符。
更新一条记录与插入操做很是类似:
QSqlQuery query; query.exec("UPDATE employee SET salary = 70000 WHERE id = 1003");
你也可使用名称或位置绑定来关联实际的参数值。
最后,下面给出一条删除语句:
QSqlQuery query; query.exec("DELETE FROM employee WHERE id = 1007");
4 事务
若是底层的数据库引擎支持事务,那么QSqlDriver::hasFeature(QSqlDriver::Transactions)会返回true。可使用QSqlDatabase::transaction()启动一个事务,而后编写一些但愿在事务中执行的SQL语句,最后调用QSqlDatabase::commit()或者QSqlDatabase::rollback()。当使用事务时必须在建立查询之前就开始事务,例如:
QSqlDatabase::database().transaction(); QSqlQuery query; query.exec("SELECT id FROM employee WHERE name = 'Torild Halvorsen'"); if (query.next()) { int employeeId = query.value(0).toInt(); query.exec("INSERT INTO project (id, name, ownerid) " "VALUES (201, 'Manhattan Project', " + QString::number(employeeId) + ')'); } QSqlDatabase::database().commit();
事务能够保证一个复杂操做的原子性,就是对于一个数据库操做序列,这些操做要么所有作完,要么一条也不作,它是一个不可分割的工做单位。