软件开发流程大致分为以下步骤
系统设计中一个重要的环节就是觀库设计,数据库设计的时候需要先进行数据建模(实体关系图E-R图) ,数据建模的依据就是前期所做的需求分析.
数据建模大致分为三个阶段:
其中概念建模和逻辑建模阶段与数据库厂商毫无关系,换言之,与MySQL,
SQLServer, Oracle没有关系。
物理建模阶段和数据库厂商存在很大的联系, 因为不同厂商对同一功能的支持方式不同,如高可用性,读写分离,甚至是索引, 分区等。
在概念建模阶段,主要做三件事:
也是一个迭代,如果先有需求,尽置去理解需求,明白当前项目或者 软件需要完成什么,不明白或者不确定的地方和客户及时交流,和客户 double confirm过的需求,落实到实体;但是好多时候我 们需要通过先和客户交流,进而将交流结果落实到需求,之后进一步具 体到实体
注意:实体类似于java中的类。后面会细讲实体
在一个B2C电子商务网站中,这样的需求再普通不过了:客户可以 在该网站上自由进行购物!
我们就以这个简单例子,对其进行细分,来讲解整个数据建模的过程,通过上面这句话,我们可以得出最起码的三个实体:
对概念建模阶段的实体进行细化,细化成具体的表同时丰富表结构
这个阶段的产物是,形成一张实体关系图。 这张关系图中丰富了实体结构,同时展示了实体与实体之间的关系。在实际开发过程中,数据库的设计核心就是实体关系图的设计。
将在逻辑建模阶段创建的实体关系图转为相应的 SQL代码,运行来创建相应具体数据库对象。但是这个阶段们不仅仅创建数据库对象,针对业务需求,我们也可能做如数 据拆分水平或垂直拆分)。
如B2B网站,我们可以将商家和 一般用户放在同_张表中,但是针表现考虑,我们可以将其分 为两张表;随业务量的上升,表数据越来越大,整个系统越来越慢,这个时我们可以考虑数据拆分,甚至是读写分离,这个阶段
也会涉及到集群的事情。
如果你是架构师或者数据建模师,这 个时候你可以跟 DBA 说,Alright,! am done with it,now is your show time。
注意:物理建模根不同类型的数据哭有很大的关系,不同类型的数据库sql代码不一样。
在逻辑建模阶段,最终的产物就是实体关系图。
实体关系图(Entity Relationship Diagram) 也叫 ER图,用来描述现实世界的概念模型。
构成ER图的三大要素: 实体, 属性, 关系。
概念
用来表示据有相同特征和性质的事物。(类似于Java中的类)
实体由实体名和实体属性组成。
概念
实体所具有的某一特性,一个实体可以拥有多个属性
概念
实体彼此之间的连接方式
类型
1:1 (丈夫实体和妻子实体)
1:N(班主任实体和班级学生实体)
N:M(学生和老师)
may-be & must-be
在实体与实体之间的关系中,都会存在着may-be和must-be
例如: 系统中有顾客
和订单
俩个实体(1 :N关系)。
一个顾客对应多个 订单,一个订单对应一个顾客。
一个顾客可以(may be)没有订单 和 他对应,一个订单一定(must be)会有顾客和它对应.
#
唯一*
非空#*
非空唯一,将来要用来做主键o
代表可有可无虚线
代表 mybe 表示 顾客可能没有订单实现
表示 must be 订单一定有着顾客物理建模就是将ER图转换为 SQL语句,在之前我们先要了解两个概念主外键
。
主键就是用来唯一标识一行数据的列。例如一个人可能就是一个数据。身份证号码唯一标识一个人的数据。那么这个号码就是主键。
能做主键的列必要满足非空唯一的特点
只要满足非空唯一的任何列都可以做主键
可以让表中一个有意义的列做主键,比如说学号,它既表示学 生学号又作为表中的主键,因为这个列满足非空唯一的条件
可以找一个没有意义的列做主键,就是用来唯一标识一行 记录的,大部分情况下都是用没有意义的列去坐主键
可以让多个列联合在一起做表中的主键,那么它就是联 合主键,要求这几个列的值联合在一起是非空唯一的
表中的某一个列声明为外键列,一般这个外键列都会引 用于另外一张表的主键列的值(有唯一约束的列就可以,不一定非要引用主键列)
一张表的主键列中出现过的值都可以在外键列中使用,没有出现过的值,都可以能使用
外键列值也可以为空的,提前是这个外键列在另一张表中不做主键
如果把B表中的联合主键的值引用到A表中做外键因为是 俩个列在B表中做联合主键,那么A表引用过来的时候也要把俩个列的值都引用过来,那么它们在A表中就会作为联合外键出现
经过上面的例子我们基本上可以去创建表了,但是设计数据哭时需要满足一定的规范,这种规范称为范式,不同的范式层级递增。范式越高,数据库冗余越小。
第一范式(1NF)
列不可再分。一张表中每个列的值是不可再分的。
例如设计一张表,表中有一列是部门
。
这个列的值可能会存储 部门编号,名字。也就是说这个列是可分割的。因此这个设计不满足第一范式。
注意:设计表时最低满足第一范式。
第二范式(2NF)
在满足第一范式基础上,表中所有非主键列都必须依赖于主键列。
订单表 : 订单编号(主键)
订单编号 订单名称 订单日期 订单中产品的生产地
这几个非主键列中,产品生产地是不依赖于订单编号的,所以 这种设计是不满足第二范式
第三范式(3NF)
在满足第二范式的基础上,表中的非主键列都必须直接依赖于主键列,而不能间接的依赖.(不能产生依赖传递)
例妣
订单表:订单编号 (主键)
订单编号 订单名称 顾客编号 顾客姓名
顾客编号依赖于订单编号,顾客姓名依赖于顾客编号。也就是说 顾客姓名 间接依赖订单编号。这种设计不符合第三范式。
一般来说数据库只需要满足第三范式就基本上可以了。
巴斯-科德范式(BCNF)
第四范式(4NF)
第五范式(5NF)
有了上面的基础,我们就可以根据ER图去建表了。
语法
-- 格式1
create table 表名(
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型]
);
-- 格式2
create table 表名(
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
字段名 数据类型 [列约束类型],
[表级约束],
[表级约束]
);
表名
数据类型
char varchar varchar2 都是存储字符串
char 存储数据的长度是固定的。varchar2 存储数据的长度是可变的。
char 效率比 varchar2效率高。 varchar是数据库标准类型,varchar2 oracle所特有
varchar2不能存空字符串,可以存空。varchar可以存空字符串
oracle 建议使用 varchar2
number(p,s) 可以存整数和浮点数 p 表示最大位数, s表示小数位,也可以为负数。
date 日期类型,存储日期
blob 存二进制对象,例如视频,音频 图片等。
clob 存储大文本,例如 xml 等
注意 blob & clob 不会在实际项目中使用。因为特别消耗资源。
约束
列级约束写在列后面,表示约束写在所有列后面。
普通建表例子(列级约束)
create table student(
id number primary key,
name varchar2(20) not null,
age number,
birthday date
);
drop table student;
create table student(
id number primary key,
name varchar2(20) not null,
email varchar2(20) unique
gender varchar2(20) check(gender in ('f','m')),
birthday date
);
drop table student;
普通建表(表级约束)
create table student(
id number,
name varchar2(20) not null,
age number,
email varchar2(100),
gender char,
primary key(id),
unique(email),
check(gender in('f','m')
);
注意 not null 没有表级约束
建表(主外键关系 列级约束)
create table t_customer(
id number primary key,
name varchar2(255)
);
create table t_order(
id numner primary key,
content varchar2(2) not null,
t_customer_id number references t_customer(id)
)
-- 必须新建t_customer 然后再建 t_order
-- 删除表(必须先删除有外键的表)
drop table t_order;
drop table t_customer;
--如果非要直接删除t_customer
drop table t_customerr cascade constraints;
建表(表级约束)
create table t_customer(
id number primary key,
name varchar2(255)
);
create table t_order(
id numner primary key,
content varchar2(2) not null,
t_customer_id number,
foreign key(t_customer_id) references t_customer(id)
)
-- 必须新建t_customer 然后再建 t_order
-- 删除表(必须先删除有外键的表)
drop table t_order;
drop table t_customer;
--如果非要直接删除t_customer
drop table t_customerr cascade constraints;
建立联合主键
-- 联合主键必须使用表级约束
create table student(
id number,
name varchar2(20),
email varchar2(20) unique
gender varchar2(20) check(gender in ('f','m')),
birthday date
primary key(id,name)
);
联合唯一约束
-- 联合唯一约束必须使用表级约束
create table student(
id number,
name varchar2(20),
email varchar2(20) unique
gender varchar2(20) check(gender in ('f','m')),
birthday date
unique(id,name)
);
联合外键
create table t_customer(
id number,
name varchar2(255),
primary key(id,name);
);
create table t_order(
id numner,
content varchar2(2) not null,
t_customer_id number,
t_customer_name varchar(255),
foreign key(t_customer_id,t_customer_name) references t_customer(id,name)
)
约束总结:
contraint
建立一张和s_dept一摸一样的表,并且表里面的数据也要样
create table 表名
as
select 语句;
create table s_dept_backup
as
select * from s_dept;
建立一张和s_dept一摸一样的表,只需要表结构,不需要数据
create table s_dept_backup
as
select * from s_dept
where 1 = 2;
建立一张和s_emp一摸一样的表,只需要表 id,last_name结构,同时只要前10行数据
create table s_emp_backup
as
select id,last_name from s_emp
where rownum <= 10;