Qt入门学习之数据库操作指南

目录
  • 一、数据库
    • 1.数据库驱动
    • 2.查询驱动
    • 3.连接数据库
    • 4.执行sql语句
    • 5.插入数据
    • 6.事务
  • 二 ,sql模型类
    • 1.QSqlQueryModel模型
    • 2.QSqlTableModel模型
    • 3.QSqlRelationalTableModel模型
  • 总结

一、数据库

Qt中的Qt SQL模块提供了对数据库的支持,模块中类可分为三层:驱动层,sql接口层,用户层。

  • 驱动层:(QSqlDriver,QSqlDriverCreator,QSqlDriverCreatorBase,QSqlDriverPlugin)为具体的数据库和SQL接口层之间提供了底层的桥梁;
  • SQL接口层:(QSqlDatabase,QSqlQuery,QSqlError,QSqlRecord)提供了对数据库的访问,其中QSqlDatabase类用来创建连接,QSqlQuery类可以使用SQL语句来实现与数据库交互;
  • 用户接口层:(QSqlTableModel,QSqlQueryModel,QSqlRelationalTableModel)实现了将数据库中的数据链接到窗口部件上,这些类是使用模型/视图框架实现的,它们是更高层次的抽象;

1.数据库驱动

Qt SQL模块使用数据库驱动插件来和不同的数据库接口进行通信。由于Qt SQL模块的接口是独立于数据库的,所以所有数据库特定的代码都包含在了这些驱动中。Qt默认支持一些驱动:

驱动名称 数据库
QSQLITE2 SQLite2版本
QSQLITE SQLite3版本
QMYSQL MySQL
QODBC SQL Service
QPSQL PostgreSQL(>=7.3版本)

2.查询驱动

#include <QApplication>
#include <QSqlDatabase>
#include <QDebug>
#include <QStringList>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QStringList drivers = QSqlDatabase::drivers();
    foreach(QString driver, drivers)
        qDebug() << driver;
    return a.exec();
}

在.pro文件中加入sql模块

3.连接数据库

数据库连接使用连接名来定义,而不是使用数据库名,可以向相同的数据库创建多个连接。QSqlDatabase也支持默认连接的概念,默认连接就是一个没有命名的连接。在使用QSqlQuery或者QSqlQueryModel的成员函数时需要指定一个连接名作为参数,如果没有指定,那么就会使用默认连接。

原型:QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const
QString &connectionName = QLatin1String( defaultConnection ))

QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("127.0.0.1");
db.setDatabaseName("book");
db.setUserName("root");
db.setPassword("123456");
if(!db.open())
{
	qDebug() << "fail to connect mysql" << db.lastError().text();
}

创建两个名为“first”和“second”的连接:

QSqlDatabase firstDB = QSqlDatabase::addDatabase("QMYSQL", "first");
QSqlDatabase secondDB = QSqlDatabase::addDatabase("QMYSQL", "second");

创建完连接后,可以在任何地方使用QSqlDatabase::database()静态函数通过连接名称获取指向数据库连接的指针,如果调用该函数时没有指明连接名称,那么会返回默认连接,例如:

QSqlDatabase defaultDB = QSqlDatabase::database();
QSqlDatabase firstDB = QSqlDatabase::database("first");
QSqlDatabase secondDB = QSqlDatabase::database("second");

要移除一个数据库连接,需要先使用QSqlDatabase::close()关闭数据库,然后使用静态函数QSqlDatabase::removeDatabase()移除该连接。

连接SQL Server数据库

QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setDatabaseName(QString("DRIVER={SQL SERVER}SERVER=%1;DATABASE=%2;UID=%3;PWD=%4;")
                   .arg("IP").arg("dbname").arg("user").arg("password"));
bool ok =db.open();

连接SQLite数据库

QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE");
db1.setHostName("IP");
db1.setDatabaseName("dbname");
db1.setUserName("user");
db1.setPassword("password");

4.执行sql语句

QSqlQuery类提供了一个接口,用于执行SQL语句和浏览查询的结果集。要执行一个SQL语句,只需要简单的创建一个QSqlQuery对象,然后调用QSqlQuery::exec()函数即可。

QSqlQuery query;
query.exec("select * from student");

QSqlQuery提供了对结果集的访问,可以一次访问一条记录。当执行完exec()函数后,QSqlQuery的内部指针会位于第一条记录前面的位置。必须调用一次QSqlQuery::next()函数来使其前进到第一条记录,然后可以重复使用next()函数来访问其他的记录,直到该函数的返回值为false,

while(query.next())
{
	qDebug() << query.value(0).toInt() << query.value(1).toString();
}

在QSqlQuery类中提供了多个函数来实现在结果集中进行定位,比如next()定位到下一条记录,previous()定位到前一条记录,first()定位的第一条记录,last()定位到最后一条记录,seek(n)定位到第n条记录。当前行的索引可以使用at()返回;record()函数可以返回当前指向的记录。

5.插入数据

插入一条记录

query.exec("insert into student (id, name) values (1, 'LI')");

同一时间插入多条记录,可以使用占位符来完成。Qt支持两种占位符:名称绑定和位置绑定。

1名称绑定

query.prepare("insert into student (id, name) values (:id, :name)");
int idValue = 1;
QString nameValue = "Li";
query.bindValue(":id", idValue);
query.bindValue(":name", nameValue);
query.exec();

2位置绑定

query.prepare("insert into student (id, name) values (?, ?)");
int idValue = 1;
QString nameValue = "Li";
query.addBindValue(idValue);
query.addBindValue(nameValue);
query.exec();

当要插入多条记录时,只需要调用QSqlQuery::prepare()一次,然后使用多次bindValue()或者addBindValue()函数来绑定需要的数据,最后调用一次exec()函数就可以了。其实,进行多条数据插入时,还可以使用批处理进行:

query.prepare("insert into student (id, name) values (?, ?)");
QVariantList ids;
ids << 1 << 2 << 3;
query.addBindValue(ids);
QVariantList names;
names << "Li" << "Wang" << "Liu";
query.addBindValue(names);
if(!query.execBatch())
qDebug() << query.lastError();

6.事务

事务可以保证一个复杂的操作的原子性,就是对于一个数据库操作序列,这些操作要么全部做完,要么一条也不做,是不可分割的工作单位。如果底层的数据库引擎支持事务,QSqlDriver::hasFeature(QSqlDriver::Transactions)会返回true。可以使用QSqlDatabase::transaction()来启动一个事务,然后编写希望在事务中执行的SQL语句,最后调用QSqlDatabase::commit()提交或者QSqlDatabase::rollback()回滚。使用事务必须在创建查询以前就开始事务

QSqlDatabase::database().transaction();
QSqlQuery query;
query.exec("SELECT id FROM student WHERE name = 'Li'");
if (query.next())
{
	int id = query.value(0).toInt();
    query.exec("INSERT INTO project (id, name, ownerid) "
               "VALUES (201, 'MProject', "
               + QString::number(id) + ')');
}
QSqlDatabase::database().commit();

二 ,sql模型类

Qt还提供了3个更高层的类来访问数据库,分别是QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel。
这3个类都是从QAbstractTableModel派生来的,可以很容易地实现将数据库中的数据在QListView和QTableView等项视图类中进行显示。使用这些类的另一个好处是,这样可以使编写的代码很容易的适应其他的数据源。例如,如果开始使用了QSqlTableModel,而后来要改为使用XML文件来存储数据,这样需要做的仅是更换一个数据模型

1.QSqlQueryModel模型

QSqlQueryModel提供了一个基于SQL查询的只读模型。

QSqlQueryModel *model = new QSqlQueryModel(this);
model->setQuery("select * from student");
model->setHeaderData(0, Qt::Horizontal, tr("学号"));
model->setHeaderData(1, Qt::Horizontal, tr("姓名"));
model->setHeaderData(2, Qt::Horizontal, tr("课程"));
ui->tableView->setModel(model);
ui->tableView->verticalHeader()->setHidden(true);
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

先创建了QSqlQueryModel对象,然后使用setQuery()来执行SQL语句查询整张student表,并使用setHeaderData()来设置显示的标头。后面创建了视图,并将QSqlQueryModel对象作为其要显示的模型。这里要注意,其实QSqlQueryModel中存储的是执行完setQuery()函数后的结果集,所以视图中显示的是结果集的内容。QSqlQueryModel中还提供了columnCount()返回一条记录中字段的个数;rowCount()返回结果集中记录的条数;record()返回第n条记录;index()返回指定记录的指定字段的索引;clear()可以清空模型中的结果集。

2.QSqlTableModel模型

QSqlTableModel提供了一个一次只能操作一个SQL表的读写模型,它是QSqlQuery的更高层次的替代品,可以浏览和修改独立的SQL表,并且只需编写很少的代码,而且不需要了解SQL语法。
创建数据表

QSqlQuery query;
// 创建student表
query.exec("create table student (id int primary key, "
                       "name varchar, course int)");
query.exec("insert into student values(1, '李', 10)");
query.exec("insert into student values(2, '马', 11)");
query.exec("insert into student values(3, '孙', 12)");
// 创建course表
query.exec("create table course (id int primary key, "
                       "name varchar, teacher varchar)");
query.exec("insert into course values(10, '数学', '王老师')");
query.exec("insert into course values(11, '英语', '张老师')");
query.exec("insert into course values(12, '计算机', '李老师')");

显示表:

QSqlTableModel *model = new QSqlTableModel(this);
model->setTable("student");
model->select();
// 设置编辑策略
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
ui->tableView->setModel(model);
ui->tableView->verticalHeader()->setHidden(true);
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

创建一个QSqlTableModel后,只需使用setTable()来为其指定数据库表,然后使用select()函数进行查询,调用这两个函数就等价于执行了“select * from student”语句。这里还可以使用setFilter()来指定查询时的条件。在使用该模型以前,一般还要设置其编辑策略,它由QSqlTableModel::EditStrategy枚举类型定义。

常量 描述
QSqlTableModel::OnFieldChange 所有对模型的改变都会立即应用到数据库
QSqlTableModel::OnRowChange 对一条记录的改变会在用户选择另一条记录时被应用
QSqlTableModel::OnManualSubmit 所有的改变都会在模型中进行缓存,直到调用submitAll()或者reverAll()函数

修改

// 开始事务操作
    model->database().transaction();
    if (model->submitAll())
    {
        if(model->database().commit()) // 提交
            QMessageBox::information(this, tr("tableModel"),tr("数据修改成功!"));
    } else
    {
        model->database().rollback(); // 回滚
        QMessageBox::warning(this, tr("tableModel"),tr("数据库错误: %1").arg(model->lastError().text()),QMessageBox::Ok);
    }

撤销修

model->revertAll();

查询

//全部数据
model->setTable("student");
model->select();
//进行筛选
QString name = "xxx" ;
// 根据姓名进行筛选,一定要使用单引号
model->setFilter(QString("name = '%1'").arg(name));
model->select();

升序

//id字段,即第0列,升序排列
model->setSort(0, Qt::AscendingOrder);
model->select();

删除

    // 获取选中的行
    int curRow = ui->tableView->currentIndex().row();
    // 删除该行
    model->removeRow(curRow);
    int ok1 = QMessageBox::warning(this,tr("删除当前行!"),
                tr("你确定删除当前行吗?"), QMessageBox::Yes, QMessageBox::No);
    if(ok == QMessageBox::No)
    { // 如果不删除,则撤销
        model->revertAll();
    } else { // 否则提交,在数据库中删除该行
        model->submitAll();
    }

3.QSqlRelationalTableModel模型

QSqlRelationalTableModel继承自QSqlTableModel,并且对其进行了扩展,提供了对外键的支持。一个外键就是一个表中的一个字段和其他表中的主键字段之间的一对一的映射。例如,student表中的course字段对应的是course表中的id字段,那么就称字段course是一个外键。因为这里的course字段的值是一些数字,这样的显示很不友好,使用关系表格模型,就可以将它显示为course表中的name字段的值。

QSqlRelationalTableModel *model = new QSqlRelationalTableModel(this);
model->setTable("student");
model->setRelation(2, QSqlRelation("course", "id", "name"));
model->select();
ui->tableView->setModel(model);
ui->tableView->verticalHeader()->setHidden(true);
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

Qt中还提供了一个QSqlRelationalDelegate委托类,它可以为QSqlRelationalTableModel显示和编辑数据。这个委托为一个外键提供了一个QComboBox部件来显示所有可选的数据,这样就显得更加清晰了。

view->setItemDelegate(new QSqlRelationalDelegate(view));

总结

到此这篇关于Qt入门学习之数据库操作指南的文章就介绍到这了,更多相关Qt数据库操作内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Qt数据库应用之实现数据的导入与导出

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 在经历过大大小小十几个甚至几十个纯QtWidget项目后,涉及到数据库相关的项目,几乎都有一个需求,将少量的信息数据比如设备信息.防区信息等,导出到文件保存好,然后用户可以打开该表格进行编辑,编辑完成后保存,再重新导入到软件中,这样相当于安排专人录入数据,而不是在软件中一个个新增效率低了些,甚至有些软件运行在嵌入式板子上或者一些特殊场景,不大方便现场添加编辑信息,如果是提供模板之类的让用户添加好,然后再一次性导入,这

  • Qt数据库相关应用开发总结

    目录 一.前言 二.数据库开发经验总结 三.数据库连接说明 四.数据库操作流程代码 五.数据库综合应用组件 一.前言 近期花了两个多月时间,将数据库相关的代码重新封装成了各种轮子(这条路必须打通,打通以后,相关项目只需要引入这个组件pri即可),测试了从Qt4.7到Qt6.1的各种版本,测试了odbc.sqlite.mysql.postgresql.sqlserver.oracle.人大金仓等数据库,测试了本地连接.远程连接.阿里云连接等,测试了windows.linux.mac等系统,将所有项

  • Qt数据库应用之实现通用数据库分页

    目录 一.前言 二.功能特点 三.体验地址 四.效果图 五.相关代码 一.前言 数据库分页展示,在所有的涉及到数据库记录的项目中都是需要的,除了简单的设备信息表.用户信息表这种很少几条几十条数据量的表除外,其余的日志记录表等都需要分页展示数据,少量的数据可以滚动条下拉查看完,超过百条以上的一般建议要加上分页的功能处理,不然用户查看起来明显不舒服,体验不友好,最明显的例子就是网页的搜索结果,一次性展示上万条,不仅是多余的增加了查询的压力,而且用户往往只关注最前面的几页记录,再比如查询报警记录,一般

  • pyqt5数据库使用详细教程(打包解决方案)

    关于pyinstaller打包生成exe的方法 安装pip . pyinstaller 在pycharm 的Terminal窗口中输入 pyinstaller -F -w main.py 注:输入参数的含义 -F 表示生成单个可执行文件 -w 表示去掉控制台窗口,这在GUI界面时非常有用.不过如果是命令行程序的话那就把这个选项删除吧! -p 表示你自己自定义需要加载的类路径,一般情况下用不到 -i 表示可执行文件的图标 一.出现 Cannot find existing PyQt5 plugin

  • Qt入门学习之数据库操作指南

    目录 一.数据库 1.数据库驱动 2.查询驱动 3.连接数据库 4.执行sql语句 5.插入数据 6.事务 二 ,sql模型类 1.QSqlQueryModel模型 2.QSqlTableModel模型 3.QSqlRelationalTableModel模型 总结 一.数据库 Qt中的Qt SQL模块提供了对数据库的支持,模块中类可分为三层:驱动层,sql接口层,用户层. 驱动层:(QSqlDriver,QSqlDriverCreator,QSqlDriverCreatorBase,QSqlD

  • mybatis框架入门学习教程

    MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 1.创建工程,导入jar包 创建一个java工程或者web工程都可以,然后导入mybatis的jar包和依赖包还有数据库的jar包,本人使用Oracle10g数据库

  • CI框架入门示例之数据库取数据完整实现方法

    本文实例讲述了CI框架入门示例之数据库取数据完整实现方法.是写给初学者看的,这是最简单可以调通的例子.分享给大家供大家参考.具体实现方法如下: 1.下载CI框架 2.配置 database.php配置: 为数据库服务器设置 connection 参数: 复制代码 代码如下: $db['default']['hostname'] = "your-db-host";  $db['default']['username'] = "your-username";  $db[

  • MyBatis入门学习教程(一)-MyBatis快速入门

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .2013年11月迁移到Github. iBATIS一词来源于"internet"和"abatis"的组合,是一个基于Java的持久层框架.iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO) 首先给大家介绍MyBatis的含义

  • mybatis快速入门学习教程新手注意问题小结

    什么是mybatis MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录. orm工具的基本思想 无论是用过的hibernate,mybatis,你都可以法相他们有一个共同点: 1. 从配置文件(通常是XML配置文件中)得到 ses

  • MyBatis入门学习教程-MyBatis快速入门

    目录 Mybatis 一.快速开始 1.创建 Maven 项目 2.导入 Maven 依赖 3.配置 Maven 插件 4.新建数据库,导入表格 5.编写 Mybatis 配置文件 6.编写实体类 7.编写 mapper 接口 8.编写 mapper 实现 9.Mybatis 配置文件中,添加 mapper 映射 10.编写 Mybatis 工具类 11.测试 二.日志添加 1.添加 Maven 依赖 2.添加 log4j 配置 3.Mybatis 中配置 LOG 4.执行测试 三.Mybati

  • Python入门学习Python流处理过程

    目录 Faust是一个流处理库 将kafka流中的思想移植到Python中 agent是一个async def的函数,因此它还可以异步执行其他操作 使用Kafka topic作为"预写日志" Faust支持任何类型的流数据 Faust是静态类型的 Faust简介 高可用性 分布式的 快速 灵活性 安装 绑定 下载并从源文件中安装 使用开发版本 常见问题 Faust是一个流处理库 将kafka流中的思想移植到Python中 它被用于Robinhood去构建高性能的分布式系统和实时数据通道

  • Python入门学习之Python流处理过程

    目录 Faust简介 高可用性 分布式的 快速 灵活性 安装 绑定 下载并从源文件中安装 使用开发版本 常见问题 Faust是一个流处理库,将kafka流中的思想移植到Python中 它被用于Robinhood去构建高性能的分布式系统和实时数据通道,每天处理数十亿的数据. Faust同时提供流处理和事件处理同类型的工具分享例如:Kafka Streams, Apache Spark/Storm/Samza/Flink 它不需要使用一个DSL,仅需要用到Python!这意味着你在做流处理的时候可以

  • PHP入门学习之字符串操作

    目录 字符串简介 单引号和双引号的区别 字符串的连接符 去除字符串首尾空格和特殊字符 1.trim()函数 2.Itrim()函数 3.rtrim()函数 转义.还原字符串数据 1.手动转义.还原字符串数据 2.自动转义.还原字符串数据 字符串简介 字符串是指由零个或多个字符构成的一个集合,这里所说的字符主要包含以下几种类型: 数字类型,如1.2.3等. 字母类型,如a.b.c.d等. 特殊字符,如#.$.%.^.&等. 不可见字符,如\n(换行符).\r(回车符).\t(Tab字符)等. 其中

  • Qt连接数据库并实现数据库增删改查的图文教程

    目录 1.连接数据库 2.查询数据库并显示在QTableView上 3.添加 4.修改 5.删除 6.总代码 总结 根据自己学习的内容,有关QTableView显示数据库,并实现数据库的增删改查,在这里做下总结. 1.连接数据库 先来看下连接数据库的效果图. “连接数据库”按钮的槽函数如下: void MainWindow::on_pushButton_connectDataBase_clicked() { //连接数据库 db.setHostName("127.0.0.1"); db

随机推荐