目录
QtSql模块层次结构
层次 | 描述 |
驱动层 | 实现了特定数据库与SQL接口的底层桥接,包括的支持类有QSqlDriver、QSqlDriverCreator<T>、QSqlDriverCreatorBase、QSqlDriverPlugin和QSqlResult |
数据库接口层 | QSqlDatabase类提供了数据库访问类、数据库连接操作,QSqlQuery类提供了与数据库的交互操作,其他支持类还包括QSqlError、QSqlField、QSqlTableModel和QSqlRecord |
用户结构层 | 提供从数据库数据到用于数据表示的窗体的映射,包括的支持类有QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel,这些类均依据Qt的模型/视图结构设计 |
QtSql模块提供的数据库驱动插件
驱 动 |
数据库管理系统 |
QDB2 |
IBM DB2及其以上版本 |
QIBASE |
Borland InterBase |
QMYSQL |
MySQL |
QOCI |
Oracle Call Interface Driver |
QODBC |
Open Database Connectivity(ODBC)包括微软SQL Server和其他ODBC兼容数据库 |
QPSQL |
PostgreSQL版本6.x和7.x |
QSQLITE |
SQLite版本3及其以上版本 |
QSQLITE2 |
SQLite版本2 |
QTDS |
Sybase Adaptive Server |
QtSql提供的高层接口
类 名 |
用 途 |
QSqlQueryModel |
基于任意SQL语句的只读模型 |
QsqlTableModel |
基于单个表的读写模型 |
QSqlRelationalTableModel |
QSqlTableModel的子类,增加了外键支持 |
小例子
1、创建数据库连接和表
void CreateSqlTable(QSqlDatabase& db, QSqlQuery& query)
{
//该数据库只在程序运行期间有效,等程序运行结束时就会将其销毁
db.setDatabaseName(":memory:");
//db.setHostName("LM123456"); //设置数据库主机名
db.setDatabaseName("qtDB.db"); //设置数据库名
db.setUserName("LiuXiaoMing"); //设置数据库用户名
db.setPassword("123456"); //设置数据库密码
db.open(); //打开连接
qDebug()<< db.isValid();//true
qDebug()<< db.isOpen(); //true
//创建数据库表
//id:变量名;int:类型;primary key:主键
bool success=query.exec("create table automobil(id int primary key,attribute varchar"
",type varchar,kind varchar,nation int,carnumber int,elevaltor int,distance int,oil int,temperature int)");
if(success)
qDebug()<<QObject::tr("数据库表创建成功!\n");
else
qDebug()<<QObject::tr("数据库表创建失败!\n");
}
2、插入数据
void InsertInto(QSqlQuery& query)
{
QTime t;
t.start();
//调用prepare()函数指定一个包含占位符的query,然后绑定要插入的值
query.clear();
query.prepare("insert into automobil values(?,?,?,?,?,?,?,?,?,?)");
long records = 10;
for(int i =0;i < records; ++i)
{
query.bindValue(0,i);//调用bindValue()或addBindValue()函数绑定要插入的值
query.bindValue(1,"四轮");
query.bindValue(2,"轿车");
query.bindValue(3,"富康");
query.bindValue(4,rand()%100);
query.bindValue(5,rand()%10000);
query.bindValue(6,rand()%300);
query.bindValue(7,rand()%200000);
query.bindValue(8,rand()%52);
query.bindValue(9,rand()%100);
//query.addBindValue(id); 插值单个值
bool success=query.exec();
if(!success)
{
QSqlError lastError=query.lastError(); //返回语句执行错误原因
qDebug()<< i << " "<<lastError.driverText()<<QString(QObject::tr("插入失败"));
}
}
qDebug()<<QObject::tr("插入 %1 条记录,耗时:%2 ms").arg(records).arg(t.elapsed());
#if 0
//批处理操作
query.prepare("insert into student values (:id, :name)");
QVariantList ints;
ints << 10 << 11 << 12 << 13;
query.addBindValue(ints); //插值一列
QVariantList names;
// 最后一个是空字符串,应与前面的格式相同
names << "xiaoming" << "xiaoliang"
<< "xiaogang" << QVariant(QVariant::String);
query.addBindValue(names);
if (!query.execBatch()) //进行批处理,如果出错就输出错误
qDebug() << query.lastError();
#endif
}
3、查找数据
void SelectData(QSqlQuery& query)
{
/*
seek(int n) :query指向结果集的第n条记录;
first() :query指向结果集的第一条记录;
last() :query指向结果集的最后一条记录;
next() :query指向下一条记录,每执行一次该函数,便指向相邻的下一条记录;
previous() :query指向上一条记录,每执行一次该函数,便指向相邻的上一条记录;
record() :获得现在指向的记录;
value(int n) :获得属性的值。其中n表示你查询的第n个属性。 获取第几列数据。
at() :获得现在query指向的记录在结果集中的编号。
刚执行完query.exec("select *from student");这行代码时,
query是指向结果集以外的,我们可以利用query.next()使得 query指向结果集的第一条记录。
当然我们也可以利用seek(0)函数或者first()函数使query指向结果集的第一条记录。
但是为了节省内存开销,推荐的方法是,在query.exec("select * from student");
这行代码前加上query.setForwardOnly(true);这条代码,此后只能使用next()和seek()函数。
*/
query.exec("select * from automobil"); //执行标准Sql语句
qDebug() << "exec next() :";
//开始就先执行一次next()函数,那么query指向结果集的第一条记录
if(query.next())
{
//获取query所指向的记录在结果集中的编号
int rowNum = query.at();
//获取每条记录中属性(即列)的个数
int columnNum = query.record().count();
//获取"name"属性所在列的编号,列从左向右编号,最左边的编号为0
int fieldNo = query.record().indexOf("id");
//获取id属性的值,并转换为int型
int id = query.value(0).toInt();
//获取name属性的值
QString name = query.value(fieldNo).toString();
//将结果输出
qDebug() << "rowNum is : " << rowNum
<< " id is : " << id
<< " name is : " << name
<< " columnNum is : " << columnNum;
}
//定位到结果集中编号为2的记录,即第三条记录,因为第一条记录的编号为0
qDebug() << "exec seek(2) :";
if(query.seek(2))
{
qDebug() << "rowNum is : " << query.at()
<< " id is : " << query.value(0).toInt()
<< " name is : " << query.value(1).toString();
}
//定位到结果集中最后一条记录
qDebug() << "exec last() :";
if(query.last())
{
qDebug() << "rowNum is : " << query.at()
<< " id is : " << query.value(0).toInt()
<< " name is : " << query.value(1).toString();
}
}
4、更新数据
void Update(QSqlQuery& query)
{
QTime t;
//更新记录
t.restart();
for(int i = 0;i < 10; ++i)
{
query.clear();
query.prepare(QString("update automobil set attribute=?,type=?,"
"kind=?,nation=?,"
"carnumber=?,elevaltor=?,"
"distance=?,oil=?,"
"temperature=? where id=%1").arg(i)); // i 对应 %1
query.bindValue(0,"双轮");
query.bindValue(1,"摩托");
query.bindValue(2,"大江");
query.bindValue(3,rand()%100);
query.bindValue(4,rand()%10000);
query.bindValue(5,rand()%300);
query.bindValue(6,rand()%200000);
query.bindValue(7,rand()%52);
query.bindValue(8,rand()%100);
bool success=query.exec();
if(!success)
{
QSqlError lastError=query.lastError();
qDebug()<< i << " "<<lastError.driverText()<<QString(QObject::tr("更新失败"));
}
}
qDebug()<<QObject::tr("更新 %1 条记录,耗时:%2 ms").arg(10).arg(t.elapsed());
}
5、删除数据
void Delete(QSqlQuery& query)
{
QTime t;
//删除
t.restart();
query.exec("delete from automobil where id=15"); //执行删除id为15的记录的操作
qDebug()<<QObject::tr("删除一条记录,耗时:%1 ms").arg(t.elapsed());
}
6、主函数
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
QSqlDatabase db =QSqlDatabase::addDatabase("QSQLITE");
QSqlQuery query;
CreateSqlTable(db,query);
InsertInto(query);
SelectData(query);
Update(query);
Delete(query);
system("pause");
return 0;
//return a.exec();
}
7、*.pro
QT += core
QT -= gui
QT += sql
CONFIG += c++11
TARGET = QSQLiteEx
CONFIG += c++11 console
CONFIG -= app_bundle
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target