Qt中的Qt SQL模块提供了对数据库的支持,要使用该模块时需要在项目文件(.pro文件)中添加“QT += sql"
该模块中的众多类基本上可以分为三层,如下表所示
层 | 对应的类 |
---|---|
用户接口层 | |
SQL接口层 | QSqlDatabase ,QSqlQuery,QSqlError, QSqlField, QSqlIndex, QSqlRecord |
驱动层 | QSqlDriver, QSqlDriverCreator, QSqlDriverCreatorBase, QSqlDriverPlugin, QSqlResult |
驱动层为具体数据库和SQL接口层之间提供了底层桥梁;SQL接口层中QSqlDatabase用来创建连接,QSqlQuery使用sql语句来实现与数据库的交互;用户接口层的几个类实现了将数据库中的数据连接到窗口部件上。
一、连接数据库
1.1 SQL数据库驱动
使用QSqlDatabase的静态函数drivers()可以获取可用的数据库驱动列表,比如下面代码,打印出了我所使用的QT可用的数据库驱动
QStringList drivers=QSqlDatabase::drivers();
foreach(QString driver,drivers)
qDebug()<<driver;
结果如下(不同版本QT可能会不一样)
"QSQLITE"
"QMYSQL"
"QMYSQL3"
"QODBC"
"QODBC3"
"QPSQL"
"QPSQL7"
1.2创建数据库连接
创建一个连接会创建一个QSqlDatabase类的实例饿,只有调用open()函数后该连接才可以被使用。下面代码段显示了创建一个默认连接,然后初始化一些连接信息,最后打开它。若打开成功就可以使用该连接了。
QSqlDatabase db=QSqlDatabase::addDatabase("QMYSQL");
db.setDatabaseHostName("bigblue");
db.setDatabaseName("mydb");
db.setUserName("user1");
db.setPassword("123456");
bool ok=db.open();
注意!setDatabaseName是指定连接到哪个数据库,如果数据库已经存在,则直接连接到这个数据库,如果不存在会创建该名称数据库。
addDatabase函数原型如下,第一个参数为驱动,第二参数为连接名。
static QSqlDatabase addDatabase(QSqlDriver* driver,
const QString& connectionName = QLatin1String(defaultConnection));
指定连接名的代码
QSqlDatabase firstDb=QSqlDatabase::addDatabase("QMYSQL","First");
QSqlDatabase secondDb=QSqlDatabase::addDatabase("QMYSQL","Second");
创建完连接后可以使用QSqlDatabase::databse()函数通过连接名获得连接。
QSqlDatabase defaultDb=QSqlDatabase::database();//返回默认连接
QSqlDatabase firstDb=QSqlDatabase::database("First");//返回"first"连接
QSqlDatabase secondDb=QSqlDatabase::database("Second");//返回"second"连接
1.3 移除数据库连接
要移除数据库需要使用close和removeDatabase函数,示例代码如下。
QSqlDatabase firstDb=QSqlDatabase::addDatabase("QMYSQL","First");
//使用firstdb
//......
firstDb.close();//关闭数据库
QSqlDatabase::removeDatabase("first");//移除数据库
二、 执行SQL语句
2.1 执行sql语句
要执行SQL语句只需要创建一个QSqlQuery对象,然后调用exec函数即可。代码如下
//QSqlQuery query(db);
QSqlQuery query;
query.exec("select * from student");
QSqlQuey的构造函数可以接收一个可选的QSqlDatavase对象,来指定使用的是哪一个数据库连接,如上图中注释掉的代码。
2.2 浏览结果集
执行完查询语句后,QSqlQUey的内部指针会第一条记录前面的位置,可以使用next()函数来使其前进到第一条记录,继续使用next遍历后面的记录,示例代码如下
QSqlQuery query;
query.exec("select * from student");
while(query.next())
{
qDebug()<<query.value(0).toInt()<<","<<query.value(1).toString();
}
除了next函数,另外还有几个定位函数:previous()定位到前一条记录;first()定位到第一条记录;last()定位到最后一条记录;seek(n)定位到第n条记录。at()函数可以返回当前行的索引;record函数返回当前记录。
2.3 插入、插入更新和删除记录
query.exec("insert into student (id,name) values(0,'LiMing')");
插入操作除了直接执行如上所示插入语句外,更常用的是使用占位符来完成,Qt支持两种占位符:名称绑定和位置绑定 。
名称绑定:
query.prepare("insert into student (id,name) values(:id,:name)");
int idValue=0;
QString nameValue="LiMing";
query.bindValue(":id",idValue);
query.bindValue(":name",nameValue);
query.exec()
位置绑定:
query.prepare("insert into student (id,name) values(?,?)");
int idValue=0;
QString nameValue="LiMing";
query.addValue(idValue);
query.addValue(nameValue);
query.exec()
更新和删除与插入类似。
2.4 事务
事务可以保证一个复杂操作的原子性。可以使用QSqlDatabase::transaction()来启动一个事务,然后编写一些希望在事务中执行的语句,最后调用QSqlDatabase::commit()提交事务或者QSqlDatabase::rollback()回滚事务,示例代码
QSqlDatabase::database().transaction();
QSqlQuery query1;
query1.exec("select id from employee where name='Tom'");
if(query.next())
{
int employeeId=query1.value(0).toInt();
query1.exec("insert into project(id,name,ownerid) values (201,'Manhattan Project',"+QString::number(employeeId)+')');
}
QSqlDatabase::database().commit();
return a.exec();
三、代码例子
下面例子演示了上述中的1、根据连接名创建两个不同的连接,指向不同数据库。2、执行sql语句,创建表格,插入数据。3、浏览数据。4、移除数据库连接
#include <QApplication>
#include <QSqlDatabase>
#include <QDebug>
#include <QStringList>
#include <QVariant>
#include <QMessageBox>
#include <QSqlQuery>
static bool createConnection();
int main(int argc,char* argv[])
{
QApplication a(argc,argv);
//创建数据库连接
if(!createConnection())
return -1;
//使用QSqlQuery查询连接1的整张表
//如果不把操作这一部分括起来,会因为引用计数问题,最后removeDatabase时有警告
{
QSqlDatabase db1=QSqlDatabase::database("connection1");
QSqlQuery query1(db1);
qDebug()<<"Connection1:";
query1.exec("select * from student");
while(query1.next())
{
qDebug()<<query1.value(0).toInt()<<","<<query1.value(1).toString();
}
//使用QSqlQuery查询连接1的整张表
QSqlDatabase db2=QSqlDatabase::database("connection2");
QSqlQuery query2(db2);
qDebug()<<"Connection2:";
query2.exec("select * from student");
while(query2.next())
{
qDebug()<<query2.value(0).toInt()<<","<<query2.value(1).toString();
}
//connection1和connection2的第一条记录
qDebug()<<"Connection1 last record:";
query1.last();
qDebug()<<query1.value(0).toInt()<<","<<query1.value(1).toString();
qDebug()<<"Connection2 last record:";
query2.last();
qDebug()<<query2.value(0).toInt()<<","<<query2.value(1).toString();
//移除数据库连接
db1.close();
db2.close();
}
QSqlDatabase::removeDatabase("connection1");
QSqlDatabase::removeDatabase("connection2");
return a.exec();
}
static bool createConnection()
{
//创建一个数据库连接,使用"connection1"为连接名
QSqlDatabase db1=QSqlDatabase::addDatabase("QSQLITE","connection1");
db1.setDatabaseName("my3.db");
if(!db1.open())//如果打开失败,弹出提示
{
QMessageBox::critical(0,"Cnanot open database1","Unable to establish a database connection.",QMessageBox::Cancel);
return false;
}
//指定连接
QSqlQuery query1(db1);
query1.exec("create table student (id int primary key,name varchar(20))");
query1.exec("insert into student values(0,'LiMing')");
//使用位置绑定插入
query1.prepare("insert into student(id,name) values(?,?)");
query1.addBindValue(1);
query1.addBindValue("LiuTao");
query1.exec();
//使用名称绑定插入
query1.prepare("insert into student(id,name)values(:id,:name)");
query1.bindValue(":id",2);
query1.bindValue(":name","ChenHong");
query1.exec();
//创建另一个数据库连接,使用不同的连接名,"connection2"
QSqlDatabase db2=QSqlDatabase::addDatabase("QSQLITE","connection2");
db2.setDatabaseName("my2.db");
if(!db2.open())//如果打开失败,弹出提示
{
QMessageBox::critical(0,"Cnanot open database2","Unable to establish a database connection.",QMessageBox::Cancel);
return false;
}
//指定连接
QSqlQuery query2(db2);
//创建表格插入数据
query2.exec("create table student (id int primary key,name varchar(20))");
query2.exec("insert into student values(10,'Tom')");
query2.exec("insert into student values(11,'Lucy')");
query2.exec("insert into student values(12,'Lily')");
return true;
}
运行效果