1. SQL数据库驱动
Qt SQl模块使用数据库驱动插件来和不同的数据库接口进行通信。由于Qt SQL模块的接口是独立于数据库的,所以所有数据库特定的代码都包涵在这些驱动中。
可以使用如下代码查看自己QT中所包含的数据库驱动。
//.pro
QT += sql
//main.cpp
int main(int argc,char* argv[]){
QApplication a(argc,argv);
qDebug() << "Available drivers";
QStringList drivers = QSqlDatabase::drivers();
foreach(QString driver,drivers)
qDebug() << driver;
return a.exec();
}
2.数据库操作(以sqlite为例)
- 创建数据库连接
要想使用QSqlQuery或者QSqlQueryModel来访问数据库,那么先要创建并打开一个或者多个数据库连接。数据库连接使用连接名来定义,而不是使用数据库名,可以向相同的数据库创建多个连接。QSqlDatabase也支持默认连接的概念,默认连接就是一个没有命名的连接。在使用QSqlQuery的成员函数时需要指定一个连接名作为参数,如果没有指定,那么就会使用默认连接。如果程序中只有一个数据库,那么使用默认连接是很方便的。
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); //创建默认连接数据库
db.setDatabaseName("memory");
if(!db.open()){ //打开数据库
qDebug() << "cannot open the database";
return false;
}
- 执行sql语句
QSqlQuery类提供了一个接口,用于执行SQL语句和浏览查询的结果集。要执行sql语句,只需要简单的创建一个QSqlQuery对象,然后调用QSqlQuery::exec()函数即可。
QSqlQuery query;
query.exec("create table student(id int primary key,name varchar(20))");
//使用普通的插入语句(sql语句和实际数据不分离)
query.exec("insert into student(id,name) values(1,'lllll')");
query.exec("insert into student(id,name) values(2,'cccccc')");
query.exec("insert into student(id,name) values(3,'nnnnnnn')");
在QSqlQuery的构造函数中可以接收一个可选的QSqlDatabase对象来指定使用的是哪一个数据库连接,当没有指定连接时,就是使用默认连接。如果发生了错误,exec()函数会返回false,可以使用QSqlQuery::lastError()来获取错误信息。
- 查询、浏览结果集以及插入、批量插入,更新、删除相关操作
演示代码(完整代码):
//connection.h
#include <QSqlDataBase>
#include <QDebug>
#include <QSqlQuery>
static bool createConnection1(){
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); //创建默认连接数据库
db.setDatabaseName("memory");
if(!db.open()){
qDebug() << "cannot open the database";
return false;
}
QSqlQuery query;
//使用普通的插入语句(sql语句和实际数据不分离)
query.exec("create table student(id int primary key,name varchar(20))");
query.exec("insert into student(id,name) values(1,'lllll')");
query.exec("insert into student(id,name) values(2,'cccccc')");
query.exec("insert into student(id,name) values(3,'nnnnnnn')");
return true;
}
static bool createConnection2(){
QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE","connection1"); //创建指定连接名称的数据库
db1.setDatabaseName("my1.db"); //设置数据库名称
if(!db1.open()){ //打开数据库
qDebug() << "cannot open the database";
return false;
}
QSqlQuery query1(db1); //对指定连接的数据库执行sql语句
query1.exec("create table student(id int primary key,name varchar(20))");
query1.exec("insert into student(id,name) values(1,'张三')");
query1.exec("insert into student(id,name) values(2,'李四')");
query1.exec("insert into student(id,name) values(3,'王五')");
//
QSqlDatabase db2 = QSqlDatabase::addDatabase("QSQLITE","connection2");
db2.setDatabaseName("my2.db");
if(!db2.open()){
qDebug() << "cannot open the database";
return false;
}
QSqlQuery query2(db2);
query2.exec("create table student(id int primary key,name varchar(20))");
query2.exec("insert into student(id,name) values(1,'tom')");
query2.exec("insert into student(id,name) values(2,'jiexi')");
query2.exec("insert into student(id,name) values(3,'monika')");
return true;
}
//main.cpp
#include <QCoreApplication>
#include "connection.h"
#include <QVariant>
#include <QSqlDriver>
#include <QSqlRecord>
#include <QSqlField>
#include <QSqlError>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
if(!createConnection2())return 1;
QSqlDatabase db1 = QSqlDatabase::database("connection1"); //得到指定连接名称数据库
QSqlDatabase db2 = QSqlDatabase::database("connection2");
QSqlQuery query1(db1);
query1.exec("select * from student"); //执行sql语句
//遍历结果集
while(query1.next()){ //next()函数将指向数据的指针向后移动一位
qDebug() << query1.value(0).toInt()<<" "<<query1.value(1).toString();
}
qDebug() << "------------------";
QSqlQuery query2(db2);
bool ok = query2.exec("delete from student where id = 1;"); //删除操作
bool ok1 = query2.exec("update student set name = 'zx' where id = 0;"); //更新操作
query2.exec("select * from student");
query2.seek(-1);
while(query2.next()){
qDebug() << query2.value(0).toInt()<<" "<<query2.value(1).toString();
}
qDebug() << ok;
int numRows; //总行数
//先判断该数据库驱动是否支持QuerySize特性,如果支持可以使用size()函数
if(db2.driver()->hasFeature(QSqlDriver::QuerySize)){
qDebug() << "has feature: query size";
numRows = query2.size();
}else{
qDebug() << "no feature : query size";
query2.last(); //快进到最后一个数据的前一个
numRows = query2.at() + 1; //+1就是总行数
}
qDebug() << "row number:" << numRows;
//指向索引为1的记录,即第二条记录
query2.seek(1);
//返回当前索引的值
qDebug() << "current index:" << query2.at();
//获取当前行的记录
QSqlRecord record = query2.record();
//获取记录中"id"和“name"两个字段的值
int id = record.value("id").toInt();
QString name = record.value("name").toString();
qDebug() << "id:" <<id <<"name: " << name;
//获取索引为1的字段,即第二个字段
QSqlField field = record.field(1);
//获取字段名和字段值,即:name 和 jiexi
qDebug() << "second field:" << field.name() << "field value:" << field.value().toString();
// 下面演示插入、删除、更新相关操作
// 插入语句(sql语句和实际数据分离)
// 1.名称绑定
qDebug() << "name binding";
query2.prepare("insert into student(id,name) values(:id,:name)");
int tmpId = 10;
QString tmpName = "liucan";
query2.addBindValue(tmpId,QSql::In);
query2.addBindValue(tmpName,QSql::In);
query2.exec();
// 2.位置绑定
qDebug() << "location binding";
query2.prepare("insert into student(id,name) values(?,?)");
int idValue = 11;
QString NameValue = "柳武";
query2.addBindValue(idValue);
query2.addBindValue(NameValue);
query2.exec(); //执行插入语句
query2.exec("select * from student"); //执行查询语句
query2.seek(-1); //回到初始位置,即第一个数据的前一个位置
while(query2.next()){
qDebug() << query2.value(0).toInt()<<" "<<query2.value(1).toString();
}
// 批量插入的使用
query2.prepare("insert into student(id,name) values(?,?)");
QVariantList ids;
ids << 12 << 13 << 14;
QStringList names;
names << "jacklove" << "Uzi" << "clearLove";
query2.addBindValue(ids);
query2.addBindValue(names);
if(!query2.execBatch())
qDebug() << query2.lastError();
query2.exec();
query2.exec("delete from student where id = 0");
query2.exec();
query2.exec("select * from student");
query2.seek(-1);
while(query2.next()){
qDebug() << query2.value(0).toInt()<<" "<<query2.value(1).toString();
}
return a.exec();
}
- Qt数据库事务
事务可以保证一个复杂操作的原子性,即对于一个数据库操作序列,这些操作要么全部做完,要么一条也不做,它是一个不可分割的工作单位。在Qt中,如果底层的数据库引擎支持事务,那么QSqlDriver::hasFeature(QSqlDriver::Transaction)会返回true。可以使用QSqlDatabase::transaction()来启动一个事务,然后编写一些希望在事务中执行的SQL语句,最后调用QSqlDatabase::commit()提交或者QSqlDatabase::rollback()回滚。使用事务时必须在创建查询以前就开始事务。