数据库设计中表的继承

单表继承

将所有相关的类型都存在一张表中,为所有类型的所有属性都保留一列。所以,当系统中新增添了一个子类型时,我们都需要将它的属性逐一添加进数据库表中,也就是改变表的结构,添加新的列。同时要保证2点:必须有一列能够区分出每一行的子类型;列允许空值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE Issues (
issue_id SERIAL PRIMARY KEY,
reported_by BIGINT UNSIGNED NOT NULL,
product_id BIGINT UNSIGNED,
priority VARCHAR(20),
version_resolved VARCHAR(20),
status VARCHAR(20),
issue_type VARCHAR(10), -- BUG or FEATURE
severity VARCHAR(20), -- only for bugs
version_affected VARCHAR(20), -- only for bugs
sponsor VARCHAR(50), -- only for feature requests
FOREIGN KEY (reported_by) REFERENCES Accounts(account_id)
FOREIGN KEY (product_id) REFERENCES Products(product_id)
);

实体表继承

为每个子类型建一张独立的表。每个表都包含属于父类的属性,同时也有子表所特有的属性。这种设计也比较简单明了,无非就是一种类型一张表。所以我们缺少元数据,搞清楚子表之间的关系(我们会发现数据库中某些表有重复的属性,却不知其缘由)。

类表继承

首先创建一张父表,包含了公共属性。而其他的子表通过外键去和父表关联。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CREATE TABLE Issues (
issue_id SERIAL PRIMARY KEY,
reported_by BIGINT UNSIGNED NOT NULL,
product_id BIGINT UNSIGNED,
priority VARCHAR(20),
version_resolved VARCHAR(20),
status VARCHAR(20),
FOREIGN KEY (reported_by) REFERENCES Accounts(account_id),
FOREIGN KEY (product_id) REFERENCES Products(product_id)
);
CREATE TABLE Bugs (
issue_id BIGINT UNSIGNED PRIMARY KEY,
severity VARCHAR(20),
version_affected VARCHAR(20),
FOREIGN KEY (issue_id) REFERENCES Issues(issue_id)
);
CREATE TABLE FeatureRequests (
issue_id BIGINT UNSIGNED PRIMARY KEY,
sponsor VARCHAR(50),
FOREIGN KEY (issue_id) REFERENCES Issues(issue_id)
);

在这种设计中,数据库的表之间的父子关系由元数据来确保,是一个不错的设计,唯一没有解决的是扩展问题。当需要经常增加新属性时,还是不得不改变表结构,增加新的列。

归并排序

归并排序是基础的排序算法之一,算法课中最先接触的一类算法。作为一个经典的算法,它有很多特性吸引人们去研究。不仅在于其分治思想的应用,也在于其优化空间复杂度的研究。

Sql多值属性的处理

在日常生活中会遇到一种场景——多值属性,比如电话号码,手机、工作的、家庭的、小灵通、IP电话…一个人可能拥有其中一种或者每一种。如果将这些值存储在一列中,势必要用到分隔符,这会导致sql操作的复杂、也无法确保数据的正确性。如果用多列存储,不优雅。因为每次查询一个人的电话时,需要扫描每一列;每当增加或者删除一种通讯工具时,需要重构整张表;数据库中可能存在更多的null列。不过,当我们在设计数据库时,所以如果想采用多列存储某种类似的属性,首先要保证分开的这些列是可区分的,且列的数目是固定的。

但是还有更好的办法是创建另一张新表,将多列属性转化为多行存储。(这个例子可能不是最恰当的)

1
2
3
4
5
6
7
create table communication (	
employee_id int,
tag varchar(20),
content varchar(20),
primary key (employee_id, tag),
foreign key (employee_id) references employee (id)
)

利用标签将不同的值分在多行存储起来,多列——>多行;同时又有外键关联,将人和信息联系在一起;同时查询、更新、删除都变得简单;支持或取消对某种通讯工具的支持(增加或删除某种通讯工具),也同样不需要重构数据库,只需要来个遍历,删除相应的行即可。

PS:当然了,这里所提到的多列属性是违反第一范式的设计。在一张表中,多个列拥有了相同的值域,这不能满足关系数据库的基础。关系中的每一行(每一条记录)都是从不同数据域上选择一个值而形成的组合。

Sql树状结构

最近看到了一本好书《SQL Antipatterns》,作者(Bill Karwin)非常厉害,他在关系型数据库上的开发经验非常丰富,总结出了sql设计时经常陷入的误区(反模式)。这本书的在线版本:SQL Antipatterns,非常值得一读!!!

Property Grid

这是以前在sap实习做项目的时候遇到的问题:studio中的property grid的定制。本身并不是很复杂,微软本身提供的editor具备很强的扩展性,只需要你用心地了解其使用方法,大概就齐了。└(^o^)┘

ruby的闭包

闭包这个概念,我最早是从javascript中了解到的。这个概念逐渐被所有的主流语言所接受(包括lambda)。而ruby中的闭包概念也差不太多,那么就先从ruby的代码块说起

Metaprogramming Ruby

第一次接触ruby的时候,我对于很多“黑魔法”的事情感到疑惑。相比于编译型语言,动态语言太灵活了。不过深入了解之后,我对于ruby或者松本行弘的一些想法也蛮佩服的。比如open class、完全的面向对象、纤程以及实现继承与接口继承等,印象很深刻。虽然ruby的性能经常被人诟病,但平时确实可以拿来玩玩