淘先锋技术网

首页 1 2 3 4 5 6 7

QT连接数据库

1、Qt SQL简介

在Qt中,Qt为SQL数据库提供了支持的基本模块。Qt SQL的API分为不同层

  • 驱动层
  • SQL API层
  • 用户接口层

1、驱动层

对于Qt 是基于C++来实现的框架,该层主要包括QSqlDriver,QSqlDriverCreator,QSqlDriverCreatorBase,QSqlPlugin,and QSqlResult.这一层提供了特定数据和SQLAPI层之间的底层桥梁。

2、API层

​ 对于SQL API层提供了数据库的访问相关类,其中,QSqlDatabase类进行连接,QSlqQuery可以完成于数据库的交互。除此之外,包括了还提供了QSqlError,QSqlField,QSqlIndex,and QSqlRecord类。

3、用户接口层

​ 用户接口层的几个类实现了将数据库中的数据链连接到窗口部件上,这些类是使用模型/试图框架实现的,它们是更高层次的抽象,主要包括QSqlQueryModel,QSqlTableModel,andQSqlRelationalTableModel.

2、SQLite数据库简介

对于数据库操作流程主要分为:

  • 在项目管理文件(.pro)中,增加数据库模块
  • 查看Qt对数据库的驱动的类型的支持
  • 连接数据库 打开数据库
  • 访问数据库
  • 关闭数据库
//在.pro文件第一行添加sql
QT       += core gui sql

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

//=============================文件分隔符================================
//在main.cpp文件中打印Qt所支持的数据库类型。
#include "mainwindow.h"

#include <QApplication>
#include <QSqlDatabase>
#include <QtDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    QStringList dirvers = QSqlDatabase::drivers();//获取到qt中所支持的数据库驱动类型

    foreach(QString driver,dirvers){    //遍历打印出支持的数据库类型
        qDebug() << driver;
    }
    return a.exec();
}

3、Qt SQL模块对数据库类

​ 在Qt中为SQL数据库提供驱动程序层、SQL API层和用户界面,其提供主要类的简要功能说明见5-1

​ 表5-1 Qt SQL模块包含的主要类的功能

类名称功能说明
QSqlDatabase用于与数据库建立连接
QSqlDriver访问特定sql数据库的抽象基类
QSqlDriverCreator为某个具体的数据库驱动提供SQL驱动的模板类
QSqlDriverCreatorBase所有SQL驱动器的基类
QSqlDriverPlugin用于定制QSqlDriver插件的抽象基类
QSqlErrorSQL数据错误信息,可以用于访问上一次出错的信息
QSqlField操作数据表或视图的字段的类
QSqlIndex操作数据库索引的类
QSqlQuery执行各种SQL语句的类
QSqlQueryModelSQL查询结果数据的制度数据模型,用于SQLECT查询结果数据记录的只读显示
QSqlRecord封装数据记录操作的类
QSqlRelation用于存储SQL外键信息的类,用于QSqlRelationalTabelModel数据源中设置代码字段于关联数据表的关系
QSqlRelationalDelegate用于QSqlRelationalTableModel的一个代码字段的显示和编辑代理组件一般是一个QCombBox组件,下拉列表中自动填充代码表的代码字段对应的实际内容
QSqlRelationalTableModel用于一个数据表的可编辑的数据模型,支持代码字段的外键
QSqlResult访问SQL数据库的抽象接口
QSqlTableModel编辑一个单一数据表的数据模型类

Qt SQL也是采用MVC设计思想来处理数据,现对齐主要类进行说明

  • QSqlDatabase用于建立于数据库的连接,在建立连接时,加载数据库驱动的时候,可以设置数据库类型和数据库名称。除此之外,还可以通过接口设置数据库名称,主机名,用户名和密码,其主要接口说明见表5-2

    ​ 表5-2 QSqldatabase操作主要接口

函数名称功能说明
QSqlDatabase addDatabase(const QString & type,const QString & connectionName=QLatin1String(defaultConnection))根据数据库类型,获取数据库对象并连接
void setDatabaseName(const QString &name)设置连接数据库名字
void setHostName(const QString &host)设置连接主机名字
void setPassword(const QString &Password)设置连接密码
void setUserName(const QString &name)设置连接用户名
bool open()打开连接的数据库
  • QSqlQuery执行各种SQL语句的类,在打开成功连接的数据库,则可以通过QSqlQuery的接口来访问数据中内容,其主要接口说明见表5-3.

    ​ 表5-3QSqlQuery操作主要接口

    函数名称功能说明
    QSqlQuery(const QString & query = QString(),QSqlDatabase da = QSqlDatabase())得到访问数据库QSqlQuery对象,参数1:数据库类型,参数2:
    bool exec(const QString & query)执行SQL语句访问数据库
    int at() const得到当前记录查询位置,第一条记录的为0
    bool first()检索结果中的第一条记录
    bool last()检索结果中的最后一条记录
    bool next()检索结果中的下一条记录
    QVariant value(const QString &name) const返回当前记录中名为name的字段的值

案例01:创建数据库表格

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSqlDatabase>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    /**
    *   一个QSqlDatabase对象相当于一个数据库,通常声明成成员变量
    *   所以在一个工程中,通常只是要一个对象即可
    */
    QSqlDatabase db; //对于一个工程而言,该类对象就相当于一个数据库

};
#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QSqlError>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //QSQLITE --- 它来告诉系统,连接的数据时sqlite3数据库,连接成功返回一个数据库对象(QSqlDatabase)
    db = QSqlDatabase::addDatabase("QSQLITE");//使用那个数据库就使用那个数据的类型

    db.setDatabaseName("test.db");  //数据库文件后缀为.db

    //如果想要进一步操作数据库,那么就必须进行数据库打开操作。一般放在构造函数中比较合适

    if(!db.open()){
        qDebug() << "Error falied to open" << db.lastError();
    }else{
        qDebug() << "open success";
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}


案例02:创建一个表格

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSqlDatabase> //可以用来连接和打开数据库
#include <QSqlQuery> //可以用来阵阵访问操作数据库

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QSqlDatabase db;    //声明
};
#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QSqlError>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    db = QSqlDatabase::addDatabase("QSQLITE");//初始化
    db.setDatabaseName("test.db");//创建一个名为test的数据库

    if(!db.open()){
        qDebug() << "open error" << db.lastError();
    }else{
        qDebug() << "open success!";
    }

    //访问数据库的操作主要包括:创建表 向数据库表中 插入数据、删除数据、更新数据、查询数据
    //对于数据库中的表,通常只需要创建一次,而其他的操作时可以重复的。
    QSqlQuery query;//在创建该对象时,系统会自动完成跟数控的关联

    //定义提条创建表的sql语句 表名:staff 表中的字段 id name age
    QString sqlCreate = QString("create table stall(id integer primary key autoincrement,"
                                "name vachar(20),"
                                "age int);"
                                );
    query.exec(sqlCreate);
}

MainWindow::~MainWindow()
{
    delete ui;
}


案例03:插入数据与查询

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSqlDatabase> //可以用来连接和打开数据库
#include <QSqlQuery> //可以用来阵阵访问操作数据库

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QSqlDatabase db;    //声明
};
#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QSqlError>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    db = QSqlDatabase::addDatabase("QSQLITE");//初始化
    db.setDatabaseName("test.db");//创建一个名为test的数据库

    if(!db.open()){
        qDebug() << "open error" << db.lastError();
    }else{
        qDebug() << "open success!";
    }

    //访问数据库的操作主要包括:创建表 向数据库表中 插入数据、删除数据、更新数据、查询数据
    //对于数据库中的表,通常只需要创建一次,而其他的操作时可以重复的。
    QSqlQuery query;//在创建该对象时,系统会自动完成跟数控的关联

#if 0
    //定义提条创建表的sql语句 表名:staff 表中的字段 id name age
    QString sqlCreate = QString("create table stall(id integer primary key autoincrement,"
                                "name vachar(20),"
                                "age int);"
                                );
#endif

    //插入操作
    QString sqlInsert = QString("insert into stall(name,age) values('张三',20);");
    //    query.exec(sqlCreate);
    if(!query.exec(sqlInsert)){
        qDebug() << "insert data error" << db.lastError();
    }
    QString sqlSelect = QString("select * from stall");
    if(!query.exec(sqlSelect)){
        qDebug() << "insert data error" << db.lastError();
    }else {
        while(query.next()){
            qDebug() <<query.value("name").toString();
            qDebug() << query.value("age").toInt();
        }
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}


4、数据库操作和更新数据到QT控件

  • 数据库操作:更新和删除

数据库删除操作

1、基本语法
DELETE FROM table_name
WHERE[condition];
DELETE FROM ---- 关键字
table_name ---- 表名
WHERE ---- 条件的关键字
[condition] ---- 条件表达式

具体使用

数据库更新操作

基本语法
UPDATE table_name
SET column1 = value1,column2 = value2......,columnN = valueN
WHERE [condition];

UPDATE ---- 关键字
table_name ---- 表名
SET ---- 关键字
column1 = vlaue1 ---- 要修改的字段名和所对应的值
WHERE ---- 条件的关键字
[condition] ---- 条件表达式

注意:如果是被删除的记录,它的id是2 那么删除以后,在添加数据,在自动添加不指定id的情况下,id = 2 是不会再被使用的。

  • 更新数据到QT控件

增删改查

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QSqlError>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    db = QSqlDatabase::addDatabase("QSQLITE");//初始化
    db.setDatabaseName("test.db");//创建一个名为test的数据库

    if(!db.open()){
        qDebug() << "open error" << db.lastError();
    }else{
        qDebug() << "open success!";
    }

    //访问数据库的操作主要包括:创建表 向数据库表中 插入数据、删除数据、更新数据、查询数据
    //对于数据库中的表,通常只需要创建一次,而其他的操作时可以重复的。
    QSqlQuery query;//在创建该对象时,系统会自动完成跟数控的关联

#if 0
    //定义提条创建表的sql语句 表名:staff 表中的字段 id name age
    QString sqlCreate = QString("create table stall(id integer primary key autoincrement,"
                                "name vachar(20),"
                                "age int);"
                                );
#endif

    //插入操作
#if 0
    QString sqlInsert = QString("insert into stall(name,age) values('张三',20);");
    //    query.exec(sqlCreate);
    if(!query.exec(sqlInsert)){
        qDebug() << "insert data error" << db.lastError();
    }

    //查询操作
    QString sqlSelect = QString("select * from stall");
    if(!query.exec(sqlSelect)){
        qDebug() << "insert data error" << db.lastError();
    }else {
        while(query.next()){
            qDebug() <<query.value("name").toString();
            qDebug() << query.value("age").toInt();
        }
    }
#endif
#if 0
    //删除操作
    QString sqlDelete = QString("delete from stall where id = 2");
    if(!query.exec(sqlDelete)){
        qDebug() << "insert data error" << db.lastError();
    }
#endif

    QString sqlUpdate = QString("update stall set name = '李四' where id = 3;");
    if(!query.exec(sqlUpdate)){
        qDebug() << "insert data error" << db.lastError();
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}


UI互动

在ui界面创建两个Label

右键 改变对象名称

在使用ui进行数据展示

    QString sqlSelect = QString("select * from stall;");
    if(!query.exec(sqlSelect)){
        qDebug() << "insert data error" << db.lastError();
    }else {
        while(query.next()){
            ui->nameLabel->setText(query.value("name").toString());
            //由于age是整型值 所以需要先使用一个方法将整型值变成number值
            ui->ageLabel->setText(QString::number(query.value("age").toInt()));
        }
    }

5、数据在控件QListWidget展示和操作

利用qt数据库,创建一个公司数据库(company.db),在该表中,创建一个员工表(employee),员工主要包括:用户名和密码 都使用字符串类型

2、自己设计一个数据库用来存储公司员工信息,并且可以通过界面来完成操作

数据库:commpany.db

员工表:staff

字段名有:id name age address salary

5、步骤

1、ui界面准备工作

1、创建主界面

  • ui界面创建一个List Widget 控件,并将其调整到合适大小。
  • 创建四个Pushbutton 分别为增删改查 并修改对象名称
  • 对四个增删改查按钮 转到槽创建clicked();方法
  • 创建四个 Label 和 EditLine 分别为ID 名字 地址 和 薪水 并修改对应EditLine的对象名称

2、创建主界面中的条目

  • 右键项目,创建新的mainwindow
  • 在ui界面创建一个Label 名字是ID
  • 复制一个Label,再右键 改变样式表
  • 选择背景 再选择颜色 添加背景颜色成功 复制四个 并把名字和对象名称改位ID 姓名 年龄 地址 薪水

3、将创建的条目添加到主界面中

  • pro文件中添加 sql
  • 在MainWindow.h文件中引入依赖
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
  • 在private区域创建一个数据库对象
QSqlDatabase db;

转到mainwindow.cpp文件中进行操作

 #include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //1、根据数据库类型来连接数据库
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("compary.db");
    //2、打开数据库
    if(!db.open()){
        qDebug() << "open error" << db.lastError();
    }
    //3、根据需求,创建数据库所需要的表
    QSqlQuery query;
    /**
     * @brief sqlCreateTable
     * 员工表:staff
     * 字段名有:id name age address salary
     */
    QString sqlCreateTable = QString("create table staff(id integer primary key autoincrement,"
                                     "name varchar(20),"
                                     "age int,"
                                     "address varchar(50),"
                                     "salary int);");
    if(!query.exec(sqlCreateTable)){
        qDebug() << "create error" << db.lastError();
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

//下面这些语句都是 ui中的pushbutton创建的槽
void MainWindow::on_addBtn_clicked()
{

}

void MainWindow::on_updateBtn_3_clicked()
{

}

void MainWindow::on_delBtn_clicked()
{

}

void MainWindow::on_selectBtn_clicked()
{

}

2、完成查询前后端展示

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "itemform.h"
#include <QListWidgetItem>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //1、根据数据库类型来连接数据库
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("compary.db");
    //2、打开数据库
    if(!db.open()){
        qDebug() << "open error" << db.lastError();
    }
    //3、根据需求,创建数据库所需要的表
    QSqlQuery query;
    /**
     * @brief sqlCreateTable
     * 员工表:staff
     * 字段名有:id name age address salary
     */
#if 0
    QString sqlCreateTable = QString("create table staff(id integer primary key autoincrement,"
                                     "name varchar(20),"
                                     "age int,"
                                     "address varchar(50),"
                                     "salary int);");
    if(!query.exec(sqlCreateTable)){
        qDebug() << "create error" << db.lastError();
    }
#endif

    //插入操作
    QString sqlInsert = QString("insert into staff(name,age,address,salary)"
                                "values('张三',20,'广州','12000');");

    if(!query.exec(sqlInsert)){
        qDebug() << " error insert into data" << db.lastError();
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_addBtn_clicked()
{

}

void MainWindow::on_updateBtn_3_clicked()
{

}

void MainWindow::on_delBtn_clicked()
{

}

void MainWindow::on_selectBtn_clicked()
{
    ui->listWidget->clear();//在查询数据之前,清空列表上的内容
    QSqlQuery query;//定义一个查询的返回对象

    //1、向数据库下达查询数据的命令
    QString sqlSelect = QString("select * from staff;"); //定义一个查询语句

    if(!query.exec(sqlSelect)){
        qDebug() << "Select from data" << db.lastError();
    }
    //遍历数据库记录
    while(query.next()){
        int id = query.value("id").toInt();
        QString name = query.value("name").toString();
        int age = query.value("age").toInt();
        QString address = query.value("address").toString();
        int salary = query.value("salary").toInt();

        qDebug() << "id = " << id << "name = " << name << "age = " << age << "address = " << address << "salary = " << salary;


        //每遍历一条记录,就要更新UI控件上
        //3.1 创建一个列表条目 先引入条目的头文件
        itemForm * staffitem = new itemForm;
        staffitem->setStaffInfo(id,name,age,address,salary);

        //这个就是显示的数据表格 上面是表格中的每一个条数据 两者要结合起来
        QListWidgetItem * item = new QListWidgetItem;
        item->setSizeHint(QSize(877,102));  //将每一条数据的宽高设置到表格大框中
        /**
     *  此处当前的理解是 创建一个条目,但是还要将这个条目和QListWidget下的QListWidgetItem关联起来
     *  先要将原staffitem的宽高数据设置到QListWidgetItem上,
     *  再将数据进行关联
     */

        ui->listWidget->addItem(item); //添加QListWidgetItem条目到QListWidget中
        ui->listWidget->setItemWidget(item,staffitem);  //再给这个QListWidget设置一个对应控件staffitem,两者关联
        //此时需要自定义一个类将两者关联起来 取itemfrom.h中取

    }


}

在itemFrom.h中创建方法声明

#ifndef ITEMFORM_H
#define ITEMFORM_H

#include <QMainWindow>

namespace Ui {
class itemForm;
}

class itemForm : public QMainWindow
{
    Q_OBJECT

public:
    explicit itemForm(QWidget *parent = nullptr);
    ~itemForm();

    void setStaffInfo(int id,QString name,int age,QString addr,int salary);

private:
    Ui::itemForm *ui;
};

#endif // ITEMFORM_H

在itemFrom.cpp中实现方法

#include "itemform.h"
#include "ui_itemform.h"

itemForm::itemForm(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::itemForm)
{
    ui->setupUi(this);

}

itemForm::~itemForm()
{
    delete ui;
}

void itemForm::setStaffInfo(int id, QString name, int age, QString addr, int salary)
{
    ui->idLabel->setText(QString::number(id));
    ui->nameLabel->setText(name);
    ui->ageLabel->setText(QString::number(age));
    ui->addressLabel->setText(addr);
    ui->salaryLabel->setText(QString::number(salary));
}

3、ui添加数据

注意 在传参的时候如果是数字就不需要单引号 如果是文字才需要单引号,在使用占位符的时候也是一样,先看看代替的值本身是什么。

/**
 * @brief MainWindow::on_addBtn_clicked
 * 思路:1、获取UI控件上的内容
 *
 *      2、通过数据库接口的访问,将数据插入到数据库中
 *      3、
 */
void MainWindow::on_addBtn_clicked()
{
    //获取UI控件上的内容
    QString name = ui->nameLineEdit->text();
    QString address = ui->addressEdit->text();
    QString salary = ui->salaryLineEdit->text();
    QString age = ui->ageEdit->text();
    //通过数据库接口的访问,将数据插入到数据库中
    QSqlQuery query;

    QString sqlInsert = QString("insert into staff(name,age,address,salary)"
                                "values('%1',%2,'%3',%4);").arg(name)
                                .arg(age.toInt())
                                .arg(address)
                                .arg(salary.toInt());
    if(!query.exec(sqlInsert)){
        qDebug() << "Error insert into data" << db.lastError();
    }

}

4、ui更新和删除

void MainWindow::on_updateBtn_3_clicked()
{
    ui->listWidget->clear();
    QSqlQuery query;
    QString id = ui->idLineEdit->text();
    QString address = ui->addressEdit->text();

    QString sqlUpdate = QString("update staff set address = '%1' where id = %2;")
            .arg(address).arg(id.toInt());
    if(!query.exec(sqlUpdate)){
        qDebug() << "Error update into data" << db.lastError();
    }


}

void MainWindow::on_delBtn_clicked()
{
    //1、删除数据库的记录
    QSqlQuery query;
    int id = ui->idLineEdit->text().toUInt();
    QString sqlDelete = QString("delete from staff where id = %1;").arg(id);

    if(!query.exec(sqlDelete)){
        qDebug() << "Error delete into data" << db.lastError();
    }
    //2、同时,也要删除UI控件上的内容,下标是从零开始
    ui->listWidget->takeItem(id-1);
}

6、数据库模型高级接口QSqlQueryModel使用和改进

QSqlQueryModel : Read-only data model for SQL result sets 以只读的方式的模型来询问数据库,将得的询问结果集

功能:以只读访问查询数据库数据,并把数据存放到一个结果集中,数据不能修改,如果向进行修改,那么必须要进行其他操作(重写虚函数)。

知识点一:QSqlQueryModel 模型基本使用

之前使用的是QSqlQuery 这个类来查询的 它是一条一条查询的

准备工作

  • xxx.pro中添加sql依赖
  • 头文件中添加 QSqlDatabase QSqlQuery QSqlError
  • 头文件中 声明一个QSqlDatabase db
  • cpp文件中制定数据库类型
  • 打开数据库
  • 声明一个QSqlQuery
  • 用表格形式展示就要引入一个表格依赖#include

代码

    //1、使用QSqlQueryModel来高效的查询数据库操作
    //创建QSqlQueryModel对象,并设置相关的表头信息
    
    QSqlQueryModel * model = new QSqlQueryModel;
    //利用这个对象来进行查询
    //执行SQL语句 将查询出来的结果转换成model对象
    model->setQuery("select name,age,address,salary from staff");
    //根据需求设置表头的信息
    model->setHeaderData(0,Qt::Horizontal,"Name");
    model->setHeaderData(1,Qt::Horizontal,"age");
    model->setHeaderData(2,Qt::Horizontal,"address");
    model->setHeaderData(3,Qt::Horizontal,"salary");
    
    //给ui控件设置一个模型
    QTableView * view = new QTableView(ui->centralwidget);//参数是父对象
    
    //设置窗口大小
    view->setFixedSize(QSize(this->width(),this->height()));
    view->setModel(model);//相当于将数据联动到UI控件上
    
    //将view显示
    view->show();

对返回的不可修改的数据进行修改

接口一

[virtual]

bool setData(const QModelIndex &index,const QVariant &value,int role = Qt::EditRole)

接口二

[override virtual]

Qt::ItemFlags flags(const QModelIndex &index) const

.h文件

#ifndef EDITQUERYMODEL_H
#define EDITQUERYMODEL_H
#include <QSqlQueryModel>

class editQueryModel : public QSqlQueryModel
{
public:
    editQueryModel();

    //重写基类的虚函数
    //这就是一个普通的函数将数据设置到我们所对应的数据库中去
    bool setData(const QModelIndex &index,const QVariant &value,int role = Qt::EditRole);
    //标志
    Qt::ItemFlags flags(const QModelIndex &index) const;

private:
    //根据需求自定义接口函数
    //更新数据
    void refresh();

    //根据需求来定义修改表中的内容的接口 这里仅仅演示修改姓名
    bool setName(int userId,const QString & name);
};

#endif // EDITQUERYMODEL_H

对应的.cpp文件

#include "editquerymodel.h"
#include <QSqlQuery>
editQueryModel::editQueryModel()
{

}

//返回boolean值 去操作数据库
bool editQueryModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    //1、判断是否为有效列 员工表 --- id 用户名 --- 年龄-- 地址 --- 收入
    if(index.column()<1||index.column()>4)
        return false;

    //获取列所对应的id
    QModelIndex primaryIndex = QSqlQueryModel::index(index.row(),0);
    int id = this->data(primaryIndex).toInt();//获取表中的字段id

    //在修改行之前将数据清除。把整个model清空
    this->clear();
    bool ok;

    //根据需求修改所对应的列
    if(index.column()==1){
        ok = setName(id,value.toString());
    }

    //刷新数据
    refresh();
    return ok;
}

//返回标志位 枚举 给一个单元框 属性标志
Qt::ItemFlags editQueryModel::flags(const QModelIndex &index) const
{
    //1、获取当前单元格的编辑状态
    Qt::ItemFlags flag = QSqlQueryModel::flags(index);

    if(index.column()==1)//只给第一列设置可编辑
    //2、给现有的标志增加一个可编辑的标志
    flag = flag | Qt::ItemIsEditable;//给它设置一个可编辑的状态 这样 所有的列都是可编辑的

    return flag;
}

void editQueryModel::refresh()
{
    //相当于将数据库的数据查询出来,转换成一个model
    this->setQuery("select * from staff"); //将所有的信息变成editQueryModel类
    //将五个列名全部进行修改
    this->setHeaderData(0,Qt::Horizontal,"Name");
    this->setHeaderData(0,Qt::Horizontal,"ID");
    this->setHeaderData(2,Qt::Horizontal,"age");
    this->setHeaderData(3,Qt::Horizontal,"Address");
    this->setHeaderData(4,Qt::Horizontal,"Salary");
}

bool editQueryModel::setName(int userId, const QString &name)
{
    //相当于执行一个更新的操作
    QSqlQuery query;

    //提前准备好一个sql语句
    query.prepare("update staff set name = ? where id = ?");
    query.addBindValue(name);
    query.addBindValue(userId);
    return query.exec();
}

界面展示.cpp文件

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "editquerymodel.h"
#include <QTableView>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //1、根据数据库类型来连接数据
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("compary.db");
    //2、打开数据库
    if(!db.open()){
        qDebug() << "open error" << db.lastError();
    }
    //3、根据需求,创建数据库所需的表
    QSqlQuery query;

    QString sqlCreate = QString("create table staff(id integer primary key autoincrement,"
                                "name vachar(20),"
                                "age int,"
                                "address varchar(50),"
                                "salary int);");
    query.exec(sqlCreate);

    //1、创建模型对象
    editQueryModel *model = new editQueryModel;
    model->setQuery("SELECT id,name,age,address,salary FROM staff");

    model->setHeaderData(0,Qt::Horizontal,"ID");
    model->setHeaderData(1,Qt::Horizontal,"Name");
    model->setHeaderData(2,Qt::Horizontal,"age");
    model->setHeaderData(3,Qt::Horizontal,"Address");
    model->setHeaderData(4,Qt::Horizontal,"Salary");

    //2、创建表格控件
    QTableView *view = new QTableView(ui->centralwidget);

    view->setFixedSize(QSize(this->width(),this->height()));
    view->setModel(model);
    view->show();
}

MainWindow::~MainWindow()
{
    delete ui;
}