Qt中的QtSql模块提供了对数据库的支持,该模块可以分为三大类别:用户接口层、SQL接口层、驱动层. 其中驱动层是具体数据和SQL接口层之间提供了底层的桥梁;SQL接口层提供了对数据库的访问,其中QSqlDatabase类用来创建链接,QSqlQuery类可以使用SQL语句实现与数据库的交互.
讲在多的理论还不如真刀真抢的来实战,下面我配合代码来讲解QT对数据库的基本操作.
新建空的Qt项目,项目名称databaseDriver,完成后
往项目添加新的main.cpp.connect.h 还需要在databaseDriver.pro文件中添加QT+=sql ,connect.h文件内容如下:
#ifndef CONNECTION_H
#define CONNECTION_H
#include
#include
#include
static bool createConnection()
{
QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE");
//db1.setDatabaseName(":memory:"); /* 表明是建立在内存中的数据库 */
db1.setDatabaseName("my1.db");
if (!db1.open())
{
QMessageBox::critical(0, "Cannot open database",
"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.exec("insert into student values(1, 'LiuTao')");
query1.exec("insert into student values(2, 'WangHong')");
QSqlDatabase db2 = QSqlDatabase::addDatabase("QSQLITE");
db2.setDatabaseName("my2.db");
if (!db2.open())
{
QMessageBox::critical(0, "Cannot open database",
"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(0, 'LiMing')");
query2.exec("insert into student values(1, 'LiuTao')");
query2.exec("insert into student values(2, 'WangHong')");
return true;
}
#endif // CONNECTION_H
部分讲解在注释中已经表明,本文由Linux_Google创建.
这个头文件添加了一个与数据库建立链接的函数,第一行创建了一个SQLite数据库的默认连接,设置数据库名称使用了:memory:表明这个是建立在内存中的数据,my1.db表明是建立在文件中的,db1.open()打开这个数据文件.QSqlQuery创建一个操作数据库的对象,可以传入参数是数据库文件,query1.exec是运行数据库命令的封装函数.
main.cpp文件内容如下
#include
#include
#include
#include
#include "connection.h"
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int numRows;
QApplication a(argc, argv);
qDebug() << "Available drivers:";
QStringList drivers = QSqlDatabase::drivers(); /* 查询所拥有的SQL驱动程序 */
foreach(QString driver, drivers)
qDebug() << driver;
if (!createConnection())
return 1;
QSqlDatabase db1 =QSqlDatabase::database("connection1");
QSqlQuery query1(db1);
query1.exec("select * from student");
/* next()下一条记录 previous()上一条记录,first()定位到第一条记录,last()定位到最后一条记录
seek(n)定位到第n条记录*/
while(query1.next())
{
qDebug() << query1.value(0).toInt() << query1.value(1).toString();
}
QSqlDatabase db2 =QSqlDatabase::database("connection1");
QSqlQuery query2(db2);
query2.exec("select * from student");
while(query2.next())
{
qDebug() << query2.value(0).toInt() << query2.value(1).toString();
}
/* 判断该数据库驱动是否支持QuerySize特性,如果支持,则可以使用size()函数 */
if(db2.driver()->hasFeature(QSqlDriver::QuerySize))
{
qDebug() << "has feauter:query size";
numRows =query2.size();
}
else
{
qDebug() << "no feauter:query size";
query2.last();
numRows =query2.at()+1;
}
qDebug() << "num number:" << numRows;
query2.seek(1); /* index is 1,also two line */
qDebug() << "current index:" << query2.at();
QSqlRecord record = query2.record();
int id =record.value("id").toInt();
QString name = record.value("name").toString();
qDebug() << "id:" << id << "name:" << name;
/* 获取索引为1的字段,即第二个字段,name */
QSqlField field = record.field(1);
/* 输出字段名和字段值 */
qDebug() << "second field:" << field.name() << "field value:" << field.value();
/* 下面两种情况是等价的 */
#if 1
query2.exec("insert into student (id, name) values (520, 'Linux_Google')");
#else /* 名称绑定 */
query2.prepare("inset into student (id,name) values(:id,:name)");
int idValue = 520;
QString nameValue = "Linux_Google";
query2.bindValue(":id",idValue);
query2.bindValue(":name",nameValue);
query2.exec();
//query2.prepare("insert into student (id, name) values (?, ?)");
/* 或者可以用下面几条语句替换,这个是位置绑定 */
// int idValue = 520;
// QString nameValue = "Linux_Google";
// query2.addBindValue(idValue);
// query2.addBindValue(nameValue);
// query2.exec();
#endif
query2.prepare("insert into student (id, name) values (?, ?)");
QVariantList ids;
ids << 20 << 21 << 22;
query2.addBindValue(ids);
QVariantList names;
names << "xiaoming" << "xiaoliang" << "xiaogang";
query2.addBindValue(names);
if(!query2.execBatch()) qDebug() << query2.lastError();
query2.exec("update student set name = 'xiaohong' where id = 20");
query2.exec("delete from student where id = 21");
query2.exec("delete from student where name = ChenYun");
query2.exec("select * from student");
while(query2.next())
{
qDebug() << query2.value(0).toInt() << query2.value(1).toString();
}
return a.exec();
}
QSqlDatabase::drivers()获取本机上可用的数据库驱动列表,foreach遍历输出.用createConnection建立了一个连接,然后创建了两个数据库操作对象query1,query2分别指向db1,db2.query1.next()作用是输出遍历到的库文件,输出一行后自动将索引值加1.query2.size()是来判断数据库文件的行数的,前提是看看是否支持这个函数,程序中有判断.
程序中有四种方法插入数据库文件,
直接插入
query2.exec("insert into student (id, name) values (520, 'Linux_Google')");
名称绑定插入法
query2.prepare("inset into student (id,name) values(:id,:name)");
int idValue = 520;
QString nameValue = "Linux_Google";
query2.bindValue(":id",idValue);
query2.bindValue(":name",nameValue);
query2.exec();
//query2.prepare("insert into student (id, name) values (?, ?)");
// int idValue = 520;
// QString nameValue = "Linux_Google";
// query2.addBindValue(idValue);
// query2.addBindValue(nameValue);
// query2.exec();
query2.prepare("insert into student (id, name) values (?, ?)");
QVariantList ids;
ids << 20 << 21 << 22;
query2.addBindValue(ids);
QVariantList names;
names << "xiaoming" << "xiaoliang" << "xiaogang";
query2.addBindValue(names);
if(!query2.execBatch()) qDebug() << query2.lastError();
代码中用到了一个库函数QVariant,QVariant是一种可以存储不同类型的数据结构,比QStringList更加强大.
最后一个知识点在代码中没有体现,那就是事务.用我们Linux内核的解释就是竞争冒险,原子变量操作.事务操作可以保证一个事务操作的原子性,就是对一个数据的操作序列,它会把数据库操作看成一个不可分割的工作单位.如果底层数据库支持事务的话,那么QSqlDatabase::database().transaction();来启动一个事务,QSqlDatabase::database().commit();
或QSqlDatabase::database().rollback(); 结束这个事务,当使用事务时必须在创建查询以前就开始事务,也就是说我们操作数据库用事务就需要在启动和停止之间.
文章出自:Linux_Google