Qt 学习之路 2(58):编辑数据库外键(skip)

前面几章我们介绍了如何对数据库进行操作以及如何使用图形界面展示数据库数据。本章我们将介绍如何对数据库的数据进行编辑。 当然,我们可以选择直接使用 SQL 语句进行更新,这一点同前面所说的 model/view 的编辑没有什么区别。除此之外,Qt 还为图形界面提供了更方便的展示并编辑的功能。

普通数据的编辑很简单,这里不再赘述。不过,我们通常会遇到多个表之间存在关联的情况。首先我们要提供一个 city 表:

PgSQL
CREATE TABLE city (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR);

INSERT INTO city (name) VALUES ('Beijing');
INSERT INTO city (name) VALUES ('Shanghai');
INSERT INTO city (name) VALUES ('Nanjing');
INSERT INTO city (name) VALUES ('Tianjin');
INSERT INTO city (name) VALUES ('Wuhan');
INSERT INTO city (name) VALUES ('Hangzhou');
INSERT INTO city (name) VALUES ('Suzhou');
INSERT INTO city (name) VALUES ('Guangzhou');

1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE city (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR);
 
INSERT INTO city (name) VALUES ('Beijing');
INSERT INTO city (name) VALUES ('Shanghai');
INSERT INTO city (name) VALUES ('Nanjing');
INSERT INTO city (name) VALUES ('Tianjin');
INSERT INTO city (name) VALUES ('Wuhan');
INSERT INTO city (name) VALUES ('Hangzhou');
INSERT INTO city (name) VALUES ('Suzhou');
INSERT INTO city (name) VALUES ('Guangzhou');

由于 city 表是一个参数表,所以我们直接将所需要的城市名称直接插入到表中。接下来我们创建 student 表,并且使用外键连接 city 表:

PgSQL
CREATE TABLE student (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR,
age INTEGER,
address INTEGER,
FOREIGN KEY(address) REFERENCES city(id));
1
2
3
4
5
6
CREATE TABLE student (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR,
    age INTEGER,
    address INTEGER,
    FOREIGN KEY(address) REFERENCES city(id));

我们重新创建 student 表(如果你使用的 RDBMS 支持 ALTER TABLE 语句直接修改表结构,就不需要重新创建了;否则的话只能先删除旧的表,再创建新的表,例如 sqlite)。

这里需要注意一点,如果此时我们在 Qt 中直接使用

PgSQL
INSERT INTO student (name, age, address) VALUES ('Tom', 24, 100);
1
INSERT INTO student (name, age, address) VALUES ('Tom', 24, 100);

语句,尽管我们的 city 中没有 ID 为 100 的记录,但还是是可以成功插入的。这是因为虽然 Qt 中的 sqlite 使用的是支持外键的 sqlite3,但 Qt 将外键屏蔽掉了。为了启用外键,我们需要首先使用QSqlQuery执行:

PgSQL
PRAGMA foreign_keys = ON;
1
PRAGMA foreign_keys = ON;

然后就会发现这条语句不能成功插入了。接下来我们插入一些正常的数据:

PgSQL
INSERT INTO student (name, age, address) VALUES ('Tom', 20, 2);
INSERT INTO student (name, age, address) VALUES ('Jack', 23, 1);
INSERT INTO student (name, age, address) VALUES ('Jane', 22, 4);
INSERT INTO student (name, age, address) VALUES ('Jerry', 25, 5);
1
2
3
4
INSERT INTO student (name, age, address) VALUES ('Tom', 20, 2);
INSERT INTO student (name, age, address) VALUES ('Jack', 23, 1);
INSERT INTO student (name, age, address) VALUES ('Jane', 22, 4);
INSERT INTO student (name, age, address) VALUES ('Jerry', 25, 5);

下面,我们使用 model/view 方式来显示数据:

 
QSqlTableModel *model = new QSqlTableModel(this);
model->setTable("student");
model->setSort(ColumnID_Name, Qt::AscendingOrder);
model->setHeaderData(ColumnID_Name, Qt::Horizontal, "Name");
model->setHeaderData(ColumnID_Age, Qt::Horizontal, "Age");
model->setHeaderData(ColumnID_City, Qt::Horizontal, "City");
model->select();

QTableView *view = new QTableView(this);
view->setModel(model);
view->setSelectionMode(QAbstractItemView::SingleSelection);
view->setSelectionBehavior(QAbstractItemView::SelectRows);
view->resizeColumnsToContents();

QHeaderView *header = view->horizontalHeader();
header->setStretchLastSection(true);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
QSqlTableModel *model = new QSqlTableModel(this);
model->setTable("student");
model->setSort(ColumnID_Name, Qt::AscendingOrder);
model->setHeaderData(ColumnID_Name, Qt::Horizontal, "Name");
model->setHeaderData(ColumnID_Age, Qt::Horizontal, "Age");
model->setHeaderData(ColumnID_City, Qt::Horizontal, "City");
model->select();
 
QTableView *view = new QTableView(this);
view->setModel(model);
view->setSelectionMode(QAbstractItemView::SingleSelection);
view->setSelectionBehavior(QAbstractItemView::SelectRows);
view->resizeColumnsToContents();
 
QHeaderView *header = view->horizontalHeader();
header->setStretchLastSection(true);

这段代码和我们前面见到的没有什么区别。我们可以将其补充完整后运行一下看看:

注意外键部分:City 一列仅显示出了我们保存的外键。如果我们使用QSqlQuery,这些都不是问题,我们可以将外键信息放在一个 SQL 语句中 SELECT 出来。但是,我们不想使用QSqlQuery,那么现在可以使用另外的一个模型:QSqlRelationalTableModelQSqlRelationalTableModelQSqlTableModel十分类似,可以为一个数据库表提供可编辑的数据模型,同时带有外键的支持。下面我们修改一下我们的代码:

 
QSqlRelationalTableModel *model = new QSqlRelationalTableModel(this);
model->setTable("student");
model->setSort(ColumnID_Name, Qt::AscendingOrder);
model->setHeaderData(ColumnID_Name, Qt::Horizontal, "Name");
model->setHeaderData(ColumnID_Age, Qt::Horizontal, "Age");
model->setHeaderData(ColumnID_City, Qt::Horizontal, "City");
model->setRelation(ColumnID_City, QSqlRelation("city", "id", "name"));
model->select();

QTableView *view = new QTableView(this);
view->setModel(model);
view->setSelectionMode(QAbstractItemView::SingleSelection);
view->setSelectionBehavior(QAbstractItemView::SelectRows);
view->resizeColumnsToContents();
view->setItemDelegate(new QSqlRelationalDelegate(view));

QHeaderView *header = view->horizontalHeader();
header->setStretchLastSection(true);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
QSqlRelationalTableModel *model = new QSqlRelationalTableModel(this);
model->setTable("student");
model->setSort(ColumnID_Name, Qt::AscendingOrder);
model->setHeaderData(ColumnID_Name, Qt::Horizontal, "Name");
model->setHeaderData(ColumnID_Age, Qt::Horizontal, "Age");
model->setHeaderData(ColumnID_City, Qt::Horizontal, "City");
model->setRelation(ColumnID_City, QSqlRelation("city", "id", "name"));
model->select();
 
QTableView *view = new QTableView(this);
view->setModel(model);
view->setSelectionMode(QAbstractItemView::SingleSelection);
view->setSelectionBehavior(QAbstractItemView::SelectRows);
view->resizeColumnsToContents();
view->setItemDelegate(new QSqlRelationalDelegate(view));
 
QHeaderView *header = view->horizontalHeader();
header->setStretchLastSection(true);

这段代码同前面的几乎一样。我们首先创建一个QSqlRelationalTableModel对象。注意,这里我们有一个setRelation()函数的调用。该语句说明,我们将第ColumnID_City列作为外键,参照于 city 表的 id 字段,使用 name 进行显示。另外的setItemDelegate()语句则提供了一种用于编辑外键的方式。运行一下程序看看效果:


此时,我们的外键列已经显示为 city 表的 name 字段的实际值。同时在编辑时,系统会自动成为一个QComboBox供我们选择。当然,我们需要自己将选择的外键值保存到实际记录中,这部分我们前面已经有所了解。

Qt 学习之路 2(58):编辑数据库外键的更多相关文章

  1. 《Qt 学习之路 2》目录

    <Qt 学习之路 2>目录 <Qt 学习之路 2>目录  豆子  2012年8月23日  Qt 学习之路 2  177条评论 <Qt 学习之路 2>目录 序 Qt ...

  2. Qt 学习之路 2(57):可视化显示数据库数据

    Qt 学习之路 2(57):可视化显示数据库数据(skip) 豆子 2013年6月26日 Qt 学习之路 2 26条评论 前面我们用了两个章节介绍了 Qt 提供的两种操作数据库的方法.显然,使用QSq ...

  3. Qt 学习之路 2(56):使用模型操作数据库

    Qt 学习之路 2(56):使用模型操作数据库 (okgogo: skip) 豆子 2013年6月20日 Qt 学习之路 2 13条评论 前一章我们使用 SQL 语句完成了对数据库的常规操作,包括简单 ...

  4. Qt 学习之路 2(50):自定义可编辑模型

    Home / Qt 学习之路 2 / Qt 学习之路 2(50):自定义可编辑模型 Qt 学习之路 2(50):自定义可编辑模型 豆子 2013年5月13日 Qt 学习之路 2 13条评论 上一章我们 ...

  5. Qt 学习之路 2(41):model/view 架构

    Qt 学习之路 2(41):model/view 架构 豆子 2013年1月23日 Qt 学习之路 2 50条评论 有时,我们的系统需要显示大量数据,比如从数据库中读取数据,以自己的方式显示在自己的应 ...

  6. Qt 学习之路 2(8):添加动作

    Home / Qt 学习之路 2 / Qt 学习之路 2(8):添加动作       [在WINDOWS10 QTCREATOR MENU添加无效]   Qt 学习之路 2(8):添加动作  豆子   ...

  7. Qt 学习之路 2(6):Qt 模块简介

    Home / Qt 学习之路 2 / Qt 学习之路 2(6):Qt 模块简介  豆子  2012年8月26日  Qt 学习之路 2  20条评论 Qt 5 与 Qt 4 最大的一个区别之一是底层架构 ...

  8. Qt 学习之路 2(67):访问网络(3)

    Qt 学习之路 2(67):访问网络(3) 豆子 2013年11月5日 Qt 学习之路 2 16条评论 上一章我们了解了如何使用我们设计的NetWorker类实现我们所需要的网络操作.本章我们将继续完 ...

  9. Qt 学习之路 2(66):访问网络(2)

    Home / Qt 学习之路 2 / Qt 学习之路 2(66):访问网络(2) Qt 学习之路 2(66):访问网络(2)  豆子  2013年10月31日  Qt 学习之路 2  27条评论 上一 ...

随机推荐

  1. mysql如何进行以=分割的字符串的拆分

    SUBSTRING_INDEX(str, delim, count) str: 要处理的字符串 delim: 分割符 count: 计数 如果为正数,则从左开始数,如果为负数,则从右开始数 使用示例: ...

  2. 前端xss攻击

    xss是什么 xss跨站脚本攻击(Cross Site Scripting),是一种经常出现在web应用中的计算机安全漏洞,它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌 ...

  3. s=1+2*3+4*5*6+7*8*9*10+.... C语言求解

    #include <stdio.h> /*类似斐波那契数列的计算方式 项 1 2 3 4 1 2*3 4*5*6 7*8*9*10 生成项的起始数字 1 2 4 7 和后一项的差值 1 2 ...

  4. java基础之io流总结三:字节流读写

    字节流读写适用于任何文件,包括图片,视频等. 基本字节流 一次读一个字节和一次读一个字节数组 FileInputStream fis = new FileInputStream(path); //一次 ...

  5. ASP.NET MVC 和 WebForm的权限控制

    今天主要讲一下对于ASP.NET的页面级权限控制 数据结构:用户表.角色表.权限表.角色权限派生表 为用户添加权限的数据配置后, 自定义类对MVC继承Controller 对其内置方法Initiali ...

  6. WebFlux04 SpringBootWebFlux集成MongoDB之Windows版本、WebFlux实现CRUD、WebFlux实现JPA、参数校验

    1 下载并安装MongoDB 1.1 MongoDB官网 1.2 下载 solutions -> download center 1.3 安装 双击进入安装即可 1.3.1 安装时常见bug01 ...

  7. spring aop自动代理注解配置之二

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  8. Luogu 3723 [AH2017/HNOI2017]礼物

    BZOJ 4827 $$\sum_{i = 1}^{n}(x_i - y_i + c)^2 = \sum_{i = 1}^{n}(x_i^2 + y_i^2 + c^2 - 2 * x_iy_i + ...

  9. Django框架 之 数据库与ORM

    浏览目录 数据库的配置 ORM表模型 ORM之增(create,save) ORM之删(delete) ORM之改(update和save) ORM之查(filter,value) 一.数据库的配置 ...

  10. 基于.Net平台常用的组件和框架整理

    转载自:http://www.cnblogs.com/hgmyz/p/5313983.html 基于转载进行补充 RPC框架: RPC:远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而 ...