11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)

文章目录

  • 1. 关系型数据表和实例功能
  • 2. 关系型数据模型功能实现
    • 2.1 可视化UI设计框架
    • 2.2 主窗口类定义
    • 2.3 打开数据表
    • 2.4 实际字段列表
    • 2.5 其他功能的实现

1. 关系型数据表和实例功能

由下图可以看到QSqlRelationalTableModel是QSqlTableModel的子类,QSqlRelationalTableModel可以处理关系数据表,所谓关系数据表,是指将主表里的某些字段存储为代码行变量,而代码的具体意义在另一个数据表里。

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第1张图片

表 11-5 给出了 studInfo 的字段定义,studInfo 数据表实际存储的数据示例见表 11-12,字段departID和 majorID存储的是学院代码和专业代码。

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第2张图片

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第3张图片

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第4张图片

学院代码字段 departID 的具体意义在数据表 departments 里定义,departments 表的字段结构见数据库文件,departments 表的示例数据见表11-13。

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第5张图片

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第6张图片

同样,专业数据表 majors 定义了专业代码及其专业名称,majors 表的字段结构见数据库文件,majors表的示例数据见表 11-14。majors 数据表不仅定义了专业代码的意义,还使用了学院代码字段departID,与departments 数据表发生关联。

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第7张图片

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第8张图片

在数据库设计中使用代码字段和代码表的好处:

  • 一是可以减少数据表的存储量,一个大的数据表存储代码远比存储具体文字用的存储空间少;
  • 二是代码表示的文字可能会被修改,例如学院的名称可能会修改,这时只需修改代码表里一条记录而已

QSqlRelationalTableModel 类专门用来编辑这种具有代码字段的数据表,可以很方便地将代码字段与关系数据表建立关系,在显示和编辑数据表时,直接使用关系数据表的代码意义字段的内容。实例 samp11_4演示关系型数据表使用的方法,图 11-8 是程序运行界面。

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第9张图片

实例 samp11_4使用QSqlRelationalTableModel 作为 tableView 的数据源,显示和编辑 studInfo数据表。学院和专业两个字段与代码表建立了关系,tableView 中直接显示这两个字段的文字内容,编辑时有一个下拉列表框,列表框里是代码表里全部代码意义文字。

2. 关系型数据模型功能实现

2.1 可视化UI设计框架

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第10张图片

2.2 主窗口类定义

主窗口类定义如下,定义了一个QSqIRelationalTableModel 类型的变量 tabModel 作为数据模型。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include    

#include    
#include    

#include    
#include    

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QSqlDatabase  DB; //数据库连接

    QSqlRelationalTableModel  *tabModel;//数据模型

    QItemSelectionModel *theSelection;//选择模型

    void    openTable();//打开数据表
//    void    getFieldNames();//获取字段名称
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_currentChanged(const QModelIndex &current, const QModelIndex &previous);
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

2.3 打开数据表

主窗口工具栏的“打开”按钮选择数据库文件 demodb.db3,然后调用 openTable()打开数据表,openTable()函数的代码如下:

void MainWindow::openTable()
{//打开数据表
    tabModel=new QSqlRelationalTableModel(this,DB);
    tabModel->setTable("studInfo"); //设置数据表
    tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);  //OnManualSubmit , OnRowChange
    tabModel->setSort(0,Qt::AscendingOrder);

    tabModel->setHeaderData(0,Qt::Horizontal,"学号");
    tabModel->setHeaderData(1,Qt::Horizontal,"姓名");
    tabModel->setHeaderData(2,Qt::Horizontal,"性别");
    tabModel->setHeaderData(3,Qt::Horizontal,"学院");
    tabModel->setHeaderData(4,Qt::Horizontal,"专业");

    //设置代码字段的查询关系数据表
    tabModel->setRelation(3,QSqlRelation("departments","departID","department")); //学院
    tabModel->setRelation(4,QSqlRelation("majors","majorID","major"));//专业

    theSelection=new QItemSelectionModel(tabModel);
    connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),
            this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));

    ui->tableView->setModel(tabModel);
    ui->tableView->setSelectionModel(theSelection);
    ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView)); //为关系型字段设置缺省代理组件

    tabModel->select(); //打开数据表

    ui->actOpenDB->setEnabled(false);
    ui->actRecAppend->setEnabled(true);
    ui->actRecInsert->setEnabled(true);
    ui->actRecDelete->setEnabled(true);
    ui->actFields->setEnabled(true);
}

QSqlRelationalTableModel 类的主要函数与 QSqlTableModel 相同,有一个新的函数 setRelation()用于设置代码字段的关联数据表和关联字段。setRelation()函数的定义如下:

void QSqlRelationalTableModel::setRelation(int *column*, const [QSqlRelation](qsqlrelation.html) &*relation*)

其中 column 是主表中代码字段的序号,relation 是 QSqlRelation 类型的表示关联数据表的关系。设置代码字段 departID 的关系的代码如下:

    //设置代码字段的查询关系数据表
    tabModel->setRelation(3,QSqlRelation("departments","departID","department")); //学院

第1个参数(数字3)是 departID 字段在 studInfo 表中的字段序号。

第2个参数用QSqlRelation(“departments”,“departID”,“department”)创建了一个QSqlRelation类型对象,其中,参数"departments"是代码表 departments,参数"departID"是代码字段名称,参数”department"是代码意义字段名称。

openTable()函数中还有关键的一行:

ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView)); //为关系型字段设置缺省代理组件

这是在 tableView 中为代码字段创建缺省的关系型代理组件,这样在 tableView 中编辑代码字段的内容时,才会出现一个下拉列表框,列出代码表的所有可选内容。

2.4 实际字段列表

使用 QSqlRelationalTableModel 类设置代码字段的关系后,在 tableView 中以代码意义显示代码字段的内容,其实际字段有没有变化呢?
工具栏上的按钮“字段列表”列出了 tabModel 的所有字段的名称,其代码如下:

void MainWindow::on_actFields_triggered()
{//获取字段列表
    QSqlRecord  emptyRec=tabModel->record();//获取空记录,只有字段名
    QString  str;
    for (int i=0;i<emptyRec.count();i++)
        str=str+emptyRec.fieldName(i)+'\n';

    QMessageBox::information(this, "所有字段名", str,
                             QMessageBox::Ok,QMessageBox::NoButton);
}

代码运行后的对话框如下图所示,可以看到两个代码字段departID和majorID被代码表中的代码意义字段department和major替换,但是在界面上修改参数后,数据能以代码的形式保存到原数据中。

11-4_Qt 5.9 C++开发指南_QSqlRelationalTableModel的使用(可处理关系数据表,所谓关系数据表,是指将主表里某些字段存储为代码行变量,而代码具体意义在另一个数据表里)_第11张图片

2.5 其他功能的实现

工具栏上其他“添加”“插入”“删除”“保存”“取消”等按钮的功能的实现与实例samp11_1相同,自定义槽函数on_currentChanged()的实现也与 samp11_1相同,这些功能的实现就不具体介绍了

你可能感兴趣的:(#,Qt,5.9,C++开发指南,qt,c++,数据库)