openGauss开源数据库实战二十八
文章目录
- 任务二十八 基于PowerDesigner的openGauss数据库设计
- 任务目标
- 实施步骤
- 一、在Win11上安装 PowerDesigner16
- 二、PowerDesigner快速入门
- 1.启动和配置E-R概念建模
- 2.创建数据项
- 3.创建域
- 4.创建实体
- 5.创建两个实体之间的联系
- 三、PowerDesigner上的E-R建模
- 1.只有单值属性的简单实体建模
- 2.联系无属性的二元联系建模
- 3.联系有属性的二元联系建模
- 4.具有复合属性的实体建模
- 5.弱实体及其依赖的强实体建模
- 6.具有多值属性的实体建模
- 7.建模实体的属性约束
- 8.递归联系建模
- (1)建模多对多的递归联系(网状建模)
- (2)建模一对多的递归联系(层次建模)
- 9.多元联系建模
- 10.时态属性建模
- 11.分类联系建模
- 12.聚集建模
- 四、PowerDesigner 正向数据库工程
- 五、事务设计
- 六、部署数据库脚本
- 七、反向数据库工程
任务二十八 基于PowerDesigner的openGauss数据库设计
任务目标
掌握计算机辅助软件工程(CASE)工具PowerDesigner的用法,会使用PowerDesigner设计和部署openGauss数据库应用。
实施步骤
一、在Win11上安装 PowerDesigner16
可以从大佬提供的PowerDesigner16.6测试版的安装文件PowerDesigner16.6x64_Evaluation的百度网盘链接(有效期一年)下载包装包,然后在Win11上安装,具体的安装步骤下图所示。
这里需要注意一点的是,有些朋友在下载完PowerDesigner后发现没有快捷方式,这是因为你已经把这个软件安装到Windows的Start Menu中了,迷惑性的是这里的英文Accessibility
对应着中文的辅助功能
。
到这里就安装成功了。
二、PowerDesigner快速入门
1.启动和配置E-R概念建模
在Win11中启动PowerDesigner16.6,按下图所示进行操作,配置E-R建模:
创建一个模型
创建E-R概念模型
配置E-R+Merise模型的选项
E-R模型的选项
现在我们就可以开始E-R建模了。
2.创建数据项
数据项可以被多个实体共用,例如创建一个名为name的数据项,实体INSTRUCTOR和实体STUDENT都可以有一个属性叫name。在创建数据项name时,已经给该数据项赋予了数据类型,然后就可以直接将数据项name赋给实体INSTRUCTOR和实体STUDENT作为属性。按下图进行操作,创建一个名为name的数据项。
创建数据项页面1
创建数据项页面2
创建数据项画面3
创建数据项画面4
创建数据项画面5
当我们创建完成后发现有部分错误也不用担心,我们可以直接在左侧的Object Browser栏中双击需要修改的数据项进行修改:
3.创建域
域具有数据类型和格式,在创建属性的时候可以直接将域赋予属性,这样就不需要来定义属性的数据类型和格式了。
按照下图所示进行操作,创建一个域telephone_number
4.创建实体
一个实体代表客观世界中的一类事物或者联系,是E-R模型中的基本元素。按照下图所示进行操作,在PowerDesigner中创建一个实体INSTRUCTOR。
创建实体画面1
创建实体画面2
双击我们新创建的实体Entity_1
添加属性:
然后将我们新创建的Data Item加入到Entity_1
最终会得到如下的显示情况:
按照下图所示进行操作,在PowerDesigner中为实体INSTRUCTOR创建主标识符。创建实体INSTRUCTOR时指定属性id是主键,因此不需要为实体的主标识符添加属性。
可以为实体创建多个辅助标识符,并为每个辅助标识符添加一个或者多个属性。辅助标识符也可以用于区分实体实例,只是它们没有被选为主标识符而已,在将来会被转化为一个唯一约束(可以为NULL)。
在现实世界中,为教师实体创建辅助标识符inst_ak
,并添加属性name
,意味着每个教师都不能重名。创建过程如下图所示。在实体INSTRUCTOR的图形中,用鼠标左键单击选中最下面一层的“inst_ak”,然后再双击鼠标左键,出现配置inst_ak
的画面。为辅助标识符inst_ak
添加属性name后,单击“确定”按钮。
5.创建两个实体之间的联系
首先在PowerDesigner中创建两个实体——实体INSTRUCTOR(见图29-42)和实体STUDENT(如下)。
实体INSTRUCTOR和STUDENT
然后,在PowerDesigner中开始创建实体INSTRUCTOR
和实体STUDENT
之间的联系advise
。先拖拽PowerDesigner的联系图标至画布中,如果要建模从教师到学生的联系advise
,先单击实体INSTUCTOR
,再单击实体STUDENT
,如下图所示。
和之前添加Data Item和Entity一样,在Model中找到Realations,从中添加两个Entity的关系。
==注意:==这里有一个BUG,如果初始创建的时候没有确定Entity1和Entity2,而选择之后再确定Entity,则会导致工作窗口无法显示两个关系的链接关系的线。
添加完成后如下图所示:
双击4工作区中的文字“Relationship-1”。命名联系有两种方法:如果两个实体间只有一种联系,可以使用两个实体的名字缩写inst_stu来命名,如果两个实体间有多个联系,使用实体名字缩写的方法就不行了,可以直接使用联系的名称advise(一般是动词)来命名,如下图所示。
在PowerDesigner中,创建联系基数的方法如下图所示。
在上图中,首先创建从实体INSTRUCTOR
到实体STUDENT
方向的联系基数,因为一个教师可以指导0个或者多个学生,所以基数是“0,n”;然后创建从实体STUDENT
到实体INSTRUCTOR
方向的联系基数,因为一个学生有且只能有一个指导老师,所以基数是“1,1”。然后可以查看图中间部分的文字,如果和需求一致,就证明这个建模是正确的。最后,单击“确定”按钮,就完成了实体INSTRUCTOR
和实体STUDENT
之间联系advise
的建模。
按照上面的方法,建模另外一对实体之间的联系——教师和系之间的工作联系。按前述方法,创建一个新的E-R模型。首先建模DEPARTMENT
,然后将实体INSTRUCTOR
和DEPARTMENT
建立联系,如下图所示。
三、PowerDesigner上的E-R建模
1.只有单值属性的简单实体建模
只有单值属性的简单实体在PowerDesigner上的建模方法,参看前面的例子。这里以建模教师实体INSTEUCTOR
为例,该实体具有教师工号id、姓名name、年龄age、性别sex、工资salary等单值属性,并有主标识符inst_pk(pi)和辅助标识符inst_ak(ai)这里假设所有的教师都不重名(如果有两个李明、则在名字后面添加自然数数字加以区别)。建模结束后,我们会得到下图所示的实体INSTRUCTOR:
2.联系无属性的二元联系建模
假如只需要记录教师与学生之间,教师是否指导过某个学生这个事实,除此以外不记录其他的信息,则可以在教师和学生之间创建一个二元联系advise
,该二元联系没有使用任何联系属性来对联系进行描述。可以按照前文所述的建模步骤来完成这个任务。建模结束后,得到实体INSTRUCTOR
和实体STUDENT
之间的联系advise
,如下图所示。
3.联系有属性的二元联系建模
假如需要记录教师多次指导某个学生的详细事实(时间、地点及指导内容)。很显然,这些详细事实信息无论是记录在教师实体中,还是记录在学生实体中,都不合适,而是应该记录在教师和学生之间的联系advise
上。换句话说,教师和学生的联系包含这些属性:adviseTime(时间截数据类型)、adviseLocation、adviseDescription。建模有属性联系的一个方法就是把教师每次指导学生这个动作(advise)转化为一个实体(指导事件),相当于将动词(advise)名词化(advising)。可以把每次的指导事件赋予一个人工码(advisingld)来进行标识。每个指导事件都会有教师和学生参与。当然,我们可以详细地描述这个指导事件的更为详细的信息。
首先创建一个新的实体ADVISING,如下图所示。然后把之前已经创建的实体INSTRUCTOR和实体STUDENT也放在PowerDesigner的画布中:
接下来将事件ADVISING
与参与方联系起来。注意,事件实体ADVISING
会依赖于事件的参与方。先创建实体ADVISING
和实体INSTRUCTOR
之间的联系基数,因为每次指导活动有且只有一名教师参加,所以基数是“1,1”;然后再创建实体INSTRUCTOR
和实体ADVISING
之间的联系基数,因为每个教师可以多次参与指导活动,也可以不参与任何指导活动,所以基数是“0,n”。同样要关注图29-62中中部的文字部分,确认与需求是一致的。最后单击“确定”按钮,完成实体ADVISING
和实体INSTRUCTOR
之间联系的建模,在PowerDesigner的画布上就会出现下图所示的E-R图。
重复上面的步骤,完成实体ADVISING
和实体STUDENT
之间的依赖联系建模,最后在PowerDesigner的画布上就会出现下图所示的E-R图。
然后可以将之前创建的advise
实体删除,再把此E-R模型转发为数据库代码进行检验,具体的操作图下图所示:
生成的SQL代码如下:
/*==============================================================*/
/* DBMS name: PostgreSQL 9.x */
/* Created on: 2024/12/15 20:59:35 */
/*==============================================================*/drop index Advising_Student_FK;drop index Advising_Inst_FK;drop index ADVISING_PK;drop table ADVISING;drop index INSTRUCTOR_PK;drop table INSTRUCTOR;drop index STUDENT_PK;drop table STUDENT;drop domain telephone_number;/*==============================================================*/
/* Domain: telephone_number */
/*==============================================================*/
create domain telephone_number as INT8;/*==============================================================*/
/* Table: ADVISING */
/*==============================================================*/
create table ADVISING (id INT8 not null,stuid INT8 not null,AdvisingID INT8 not null,AdvisingLocation VARCHAR(40) null,AdvisingTIme DATE null,constraint PK_ADVISING primary key (id, stuid, AdvisingID)
);/*==============================================================*/
/* Index: ADVISING_PK */
/*==============================================================*/
create unique index ADVISING_PK on ADVISING (
id,
stuid,
AdvisingID
);/*==============================================================*/
/* Index: Advising_Inst_FK */
/*==============================================================*/
create index Advising_Inst_FK on ADVISING (
id
);/*==============================================================*/
/* Index: Advising_Student_FK */
/*==============================================================*/
create index Advising_Student_FK on ADVISING (
stuid
);/*==============================================================*/
/* Table: INSTRUCTOR */
/*==============================================================*/
create table INSTRUCTOR (id INT8 not null,age INT2 null,name VARCHAR(40) null,salary NUMERIC(7,2) null,sex BOOL null,constraint PK_INSTRUCTOR primary key (id),constraint AK_INST_AK_INSTRUCT unique (name)
);/*==============================================================*/
/* Index: INSTRUCTOR_PK */
/*==============================================================*/
create unique index INSTRUCTOR_PK on INSTRUCTOR (
id
);/*==============================================================*/
/* Table: STUDENT */
/*==============================================================*/
create table STUDENT (age INT2 null,name VARCHAR(40) null,sex BOOL null,stuid INT8 not null,total_credit INT2 null,constraint PK_STUDENT primary key (stuid),constraint AK_STUDENT_AK_STUDENT unique (name)
);/*==============================================================*/
/* Index: STUDENT_PK */
/*==============================================================*/
create unique index STUDENT_PK on STUDENT (
stuid
);alter table ADVISINGadd constraint FK_ADVISING_ADVISING__INSTRUCT foreign key (id)references INSTRUCTOR (id)on delete restrict on update restrict;alter table ADVISINGadd constraint FK_ADVISING_ADVISING__STUDENT foreign key (stuid)references STUDENT (stuid)on delete restrict on update restrict;
我们对教师每次指导学生的事件都赋予了一个人工键来标识。表ADVISING的主键是(id,stuid,AdvisingID)
,所以表ADVISING可以记录每次指导活动有多少个教师和学生参与。当然,表ADVISING还记录了关于某次指导活动的详细细节——指导时间和地点以及描述。
建模有属性联系的另外一种方法是使用关联。关联没有主键,它依赖参与关联的实体来标识,因此一对实体之间的关联只能记录一次事件的信息(因为这对实体的主键联合在一起,故只能有一个取值)。例如,记录教师何时成为学生的导师。
首先创建实体INSTRUCTOR和实体STUDENT
,然后在右侧栏选中PowerDesigner中的关联图标,拖拽到PowerDesigner的画布中,会出现如下所示的画面。
在上图中用鼠标左键单击表示关联的图块,再双击鼠标左键打开关联的配置窗口,如下图所示。将关联命名为BeAdvisorOf后,单击标签“Attributes”,出现下图所示的画面:
按上图所示为关联添加属性,可以看到无法为关联创建主标识符。关联依赖于参与的实体,由参与关联的实体的主标识符联合确定关联的主标识符。单击“确定”按钮后,出现下图所示的画面:
在上图右侧单击选中表示关联联系的工具小图标,然后单击实体INSTRUCTOR
,再单击关联BeAdvisorOf
;重复一次操作,单击选中表示关联联系的工具小图标,然后单击实体STUDENT
,再单击关联 BeAdvisorOf
。PowerDesigner的画布中最后显示的画面如下图所示:
可以双击关联线,然后修改关联线上的基数。上图的语义是:一个教师可以成为0个或者多个学生的导师,一个学生只能有一个导师。
4.具有复合属性的实体建模
具有复合属性的实体,可以先将其复合属性的子属性建模为实体的单值属性。例如使用复合属性address
记录教师的联系地址,address
可能包含province
、city
、street
、buildingNo
等多个子属性。可以把这些子属性单独建模为实体集INSTRUCTOR
的一个单独属性。建模过程如下图所示:
5.弱实体及其依赖的强实体建模
弱实体不能单独存在,必须依赖于强实体。在大学里,像高等数学这样的课程(course
),会分成两个课程部分(section
),分别在一年级的第一学期和第二学期来讲授。因此,可以把course
建模成为强实体,把section
建模成为弱实体。
弱实体及其所依赖的强实体的建模过程如下:
1)按建模普通实体的方法建模强实体COURSE,如下图所示。
2)按建模普通实体的方法建模弱实体SECTION,如下图所示。
3)按建模普通实体的方法建模弱实体SECTIONCLASS,如下图所示。
4)建模强实体和弱实体之间的依赖联系,如下图所示。弱实体具有自己的分辨标识符,这个分辨标识符和该弱实体所依赖的强实体的主键一起,构成了弱实体的主键。
6.具有多值属性的实体建模
具有多值属性的实体,可以将每一个多值属性都建模为一个弱实体,它们依赖于拥有该多值属性的强实体集。例如要记录教师的多个联系电话(telnum
),这是一个多值属性,因此可以建一个弱实体集instructor_telnum
,具有属性telnum
,依赖于强实体集INSTRUCTOR
。这种建模方法也称为高表建模。
还有一种称为宽表的方法也可用来建模多值属性。该方法规定每个实体实例最多有几个这样的值。例如建模教师的电话,可以规定教师最多有三个电话,于是为教师实体添加三个属性:telnum1
、telnum2
、telnum3
。
7.建模实体的属性约束
假设我们要限制弱实体SECTIONCLASS的属性sectClassSemester只能取三个值:Spring、Summer、Autumn。在PowerDesigner的画布中,先单击选中弱实体SECTIONCLASS的属性sectClassSemester,如下图所示。
单击“StandardChecks”标签,出现上图所示的窗口,在右边的列表值栏里填上该属性可能的取值Spring、Summer和Autumn,单击“确定”按钮,完成实体属性约束的建模。
8.递归联系建模
(1)建模多对多的递归联系(网状建模)
一门课程可以有多门课程作为先修课程,一门课程还可以作为多门课程的先修课程。因为先修课程和后修课程都是课程,因此课程和先修课程之间是一个多对多的递归联系。
使用PowerDesigner建模递归联系,具体步骤如下:
1)创建实体COURSE,如下图所示。
2)创建递归联系precouse
(注意不是precourse
。联系名和角色名不能同名,此处将联系名定义为precouse
,而将角色名定义为precourse
和latercourse
。precourse
在后面被用作角色名,联系名precouse
会被转化为表名,角色名会被转化为一个外键约束)。按图29-88所示进行操作,先选中PowerDesigner工具箱中用于建模联系的小图标,然后单击实体COURSE,再单击画布中白色的位置,最后再单击实体COURSE。
双击联系线上的文字“Relationship_1”,出现下图所示的窗口,填人联系的名字precouse
,然后单击“cardinalities”标签,出现下图所示的窗口。首先定义实体的角色为latercourse
和precourse
;然后定义从latercourse
到precourse
的基数为0,n,表示一门后修课可以有0门或者多门先修课;接着定义从precourse到latercourse的基数为0,n,表示一门先修课可以有0门或者多门后修课。单击“确定”按钮,完成先修课与后修课之间的递归多对多联系建模。
3)将第2步创建的E-R模型转换为物理数据库模型(PostgreSQL数据库),如下图所示。
注意到precouse
中的一个列名COU_cid
不是很规范,直接双击该列名进行修改。
按照从下图所示进行操作,将属性COU_cid
的名字修改为preCourseID
。修改后的物理数据库模型如下图所示。
4)按照下图所示进行操作,用物理数据库模型自动生成SQL代码
代码如下:
/*==============================================================*/
/* DBMS name: PostgreSQL 9.x */
/* Created on: 2024/12/15 22:54:50 */
/*==============================================================*/drop index COURSE_PK;drop table COURSE;drop index latercourse_FK;drop index precourse_FK;drop index Precouse_PK;drop table Precouse;drop domain telephone_number;/*==============================================================*/
/* Domain: telephone_number */
/*==============================================================*/
create domain telephone_number as INT8;/*==============================================================*/
/* Table: COURSE */
/*==============================================================*/
create table COURSE (cDescription VARCHAR(400) null,chours INT4 null,cid INT8 not null,cname VARCHAR(60) null,constraint PK_COURSE primary key (cid)
);/*==============================================================*/
/* Index: COURSE_PK */
/*==============================================================*/
create unique index COURSE_PK on COURSE (
cid
);/*==============================================================*/
/* Table: Precouse */
/*==============================================================*/
create table Precouse (preCourseID INT8 not null,cid INT8 not null,constraint PK_PRECOUSE primary key (preCourseID, cid)
);/*==============================================================*/
/* Index: Precouse_PK */
/*==============================================================*/
create unique index Precouse_PK on Precouse (
preCourseID,
cid
);/*==============================================================*/
/* Index: precourse_FK */
/*==============================================================*/
create index precourse_FK on Precouse (
preCourseID
);/*==============================================================*/
/* Index: latercourse_FK */
/*==============================================================*/
create index latercourse_FK on Precouse (
cid
);alter table Precouseadd constraint FK_PRECOUSE_LATERCOUR_COURSE foreign key (cid)references COURSE (cid)on delete restrict on update restrict;alter table Precouseadd constraint FK_PRECOUSE_PRECOURSE_COURSE foreign key (preCourseID)references COURSE (cid)on delete restrict on update restrict;
(2)建模一对多的递归联系(层次建模)
下面是另外一个递归联系的例子。公司的顾客由其他顾客介绍而来,一个顾客可以介绍许多新的顾客(也可能没有介绍任何一个新顾客),但一个新的顾客必须且只能由一个老顾客介绍而来。新顾客和老顾客都是顾客,这是一个一对多的递归联系。
在PowerDesigner中建模这个一对多的递归联系,过程和建模多对多的递归联系一样,差别只是在创建联系的基数上。建模完成后,其E-R图如下图所示。为这个物理数据库模型生成SQL代码时,不选中进行模型检查选项,如下所示。
/*==============================================================*/
/* DBMS name: PostgreSQL 9.x */
/* Created on: 2024/12/15 23:26:27 */
/*==============================================================*/drop index Relationship_1_FK;drop index CUSTOMER_PK;drop table CUSTOMER;drop domain telephone_number;/*==============================================================*/
/* Domain: telephone_number */
/*==============================================================*/
create domain telephone_number as INT8;/*==============================================================*/
/* Table: CUSTOMER */
/*==============================================================*/
create table CUSTOMER (customerDescription VARCHAR(400) null,customerID INT8 not null,CUS_customerID INT8 not null,customerName VARCHAR(40) null,oldCustomerID INT8 null,constraint PK_CUSTOMER primary key (customerID)
);/*==============================================================*/
/* Index: CUSTOMER_PK */
/*==============================================================*/
create unique index CUSTOMER_PK on CUSTOMER (
customerID
);/*==============================================================*/
/* Index: Relationship_1_FK */
/*==============================================================*/
create index Relationship_1_FK on CUSTOMER (
CUS_customerID
);alter table CUSTOMERadd constraint FK_CUSTOMER_RELATIONS_CUSTOMER foreign key (CUS_customerID)references CUSTOMER (customerID)on delete restrict on update restrict;
9.多元联系建模
下面以三元联系为例,学习如何对多元联系进行建模。三元联系的一个例子是教师指导学生做项目,其中有3个实体名词和1个联系动词。建模方法可以参照前文内容。把动词advise
动名词化为advising
,使其成为一个事件,并赋予该事件人工键。该事件依赖于三个参方:INSTRUCTOR
、STUDENT
、PROJECT
。建模完成后的E-R图如下图所示。
10.时态属性建模
这里以员工在公司工作时的薪水变化情况为例进行建模,可以将其建模为一个弱实体employee_salary
(见下图):过去的工资具有开始时间和结束时间;当前的工资有开始时间,结束时间可以用日期的最大值(如9999年12月31日)来表示。还可以把员工当前的工资作为一个属性,记录在实体employee
中。
其他的例子还有:员工在不同的时期在不同的部门工作;一个部门在不同的时期有不同的管理人员。其建模方法同不同时期员工的工资。读者可在自己在PowerDesigner上实验一下。
11.分类联系建模
可以通过概化和特化的方法来对实体进行分类,二者之间的区别在于:特化是自顶向下,高层实体不断地寻找不同的特点进行分类,形成不同层次的低层实体;概化是自底向上,多个不同的低层实体不断地寻找相互之间的共同点,进行归类。
场景1(部分-相交):大学中的人可以是员工或者学生,还可以是访问学者(既不是员工也不是学生)。另外,员工也可能是学生(教师是员工,比如某教师的学历目前是硕士研究生,正在攻读博士学位,因此他同时也是一个学生)。
场景2(部分-不相交):员工可以是教师、秘书,也可以是后勤人员(目前我们的系统不关心后勤人员,但是会把后勤人员记录在员工表中);但是教师不可能是秘书,秘书不可能是教师
场景3(完全-不相交):高层实体学生,要么是一个本科生,要么是一个研究生,不会同时属于本科生和研究生。
12.聚集建模
这里以三元联系——教师指导学生做项目为例。学院要对教师指导学生做项目的情况进行评估,以此为据给学生和教师发补贴。这本质上为联系与实体之间的联系的建模(联系的联系)。
四、PowerDesigner 正向数据库工程
正向数据库工程从E-R图开始,通过E-R图生成物理数据库模型,就是基于E-R图生成了一个特定数据库管理系统(如openGaussDBMS)的数据库模式图,然后基于此模式图生成数据库部署脚本。在前文中,我们已经多次实践了通过E-R图生成数据库脚本的过程。
五、事务设计
验证之前的设计是否可以满足事务操作的需要,如果不能满足要求,需要返回重新设计,直到数据库模式的设计满足事务的要求。一旦数据库模式满足了事务操作的要求,可以根据事务中的查询设计相应的索引、约束。
六、部署数据库脚本
在数据库中执行数据库脚本,将应用的数据库模式部署到数据库管理系统中。此时可以开始开发应用程序了。
七、反向数据库工程
由于目前PowerDesigner不支持openGauss,因此反向数据库工程需要借助PostgreSQL来实现。可以将部署在openGauss上的数据库恢复到PostgreSQL上,然后使用PowerDesigner连接到PostgreSOL进行反向数据库工程。