通过 BCNF 进行标准化是基于函数依赖的。什么
数据中的函数依赖是这样的吗?什么是
候选键?
城市
州县城
--
阿拉巴马派克特洛伊
阿肯色派克喜悦
佛罗里达湾斯普林菲尔德
缅因州佩诺布斯科特斯普林菲尔德
这里只有一个(微不足道的)函数依赖,而且只有一个
候选键。唯一的 FD 是 State, County, City -> State, County,
城市。唯一的候选键是 {State, County, City}。这种关系
至少处于 5NF。
你不能改善这种关系,但你可以改善
数据库。数据库不知道没有名为“洛斯”的县
洛杉矶”在阿拉巴马州。所以它会让你插入这个无效的行。
城市
州县城
--
阿拉巴马州洛杉矶特洛伊
要修复那个问题,添加一个包含所有有效的关系
县,并设置外键引用。
县
状态
--
阿拉巴马州奥陶加
阿拉巴马州鲍德温
...
阿拉巴马派克
...
加利福尼亚洛杉矶
...
关系“Counties”是全键,没有非质数
属性。 “Counties”也至少在 5NF 中。
数据库仍然不知道它不应该允许这样的行。
城市
州县城
--
威尔士派克特洛伊
美国没有名为威尔士的州。同解决这个问题
方式作为最后一个问题。
状态
--
阿拉巴马州
阿肯色州
...
加利福尼亚
...
并设置从县到州的外键引用。
这是标准 SQL 中的样子,除了我没有
供应所有 50 个州或所有 3000 多个县。
create table states (
state varchar(100) primary key
);
insert into states values
('Alabama'), ('Arkansas'), ('California'), ('Florida'),
('Maine'); -- and more . . .
create table counties (
county varchar(100) not null,
state varchar(100) not null,
primary key (county, state),
foreign key (state) references states (state)
on update restrict on delete restrict
);
insert into counties values
('Autauga', 'Alabama'), ('Baldwin', 'Alabama'), ('Pike', 'Alabama'),
('Pike', 'Arkansas'),
('Los Angeles', 'California'),
('Bay', 'Florida'),
('Penobscot', 'Maine'); -- and more . . .
create table cities (
city varchar(100) not null,
county varchar(100) not null,
state varchar(100) not null,
primary key (city, county, state),
foreign key (county, state) references counties (county, state)
on update restrict on delete restrict
);
insert into cities values
('Troy', 'Pike', 'Alabama'),
('Delight', 'Pike', 'Arkansas'),
('Springfield', 'Penobscot', 'Maine'),
('Springfield', 'Bay', 'Florida'); -- and more . . .
现在你会发现无法插入无效元组
{Troy, Los Angeles, Alabama} 和 {Troy, Pike, Wales}。
使用代理 ID 号而不是自然键不会改变
正常形式。但它确实改变了数据库的工作方式。并不是
一定是好的。
使用上面的 SQL 表,此更新将失败。
update states
set state = 'Wibble'
where state = 'Alabama';
这是一件好事。
让我们用代理 ID 号来构建这些表。
create table states (
state_id integer primary key,
state varchar(100) not null unique
);
insert into states values
(1, 'Alabama'), (2, 'Arkansas'), (3, 'California'), (4, 'Florida'),
(5, 'Maine'); -- and more . . .
create table counties (
county_id integer not null,
county varchar(100) not null,
state_id integer not null,
foreign key (state_id) references states (state_id)
on update restrict on delete restrict,
primary key (county_id, state_id),
unique (county, state_id)
);
insert into counties values
(1, 'Autauga', 1), (2, 'Baldwin', 1), (3, 'Pike', 1),
(4, 'Pike', 2),
(5, 'Los Angeles', 3),
(6, 'Bay', 4),
(7, 'Penobscot', 5); -- and more . . .
create table cities (
city_id integer not null,
city varchar(100) not null,
county_id integer not null,
state_id integer not null,
foreign key (county_id, state_id) references counties (county_id, state_id)
on update restrict on delete restrict,
primary key (city_id, county_id, state_id),
unique (city, county_id, state_id)
);
insert into cities values
(1, 'Troy', 3, 1),
(2, 'Delight', 4, 2),
(3, 'Springfield', 7, 5),
(4, 'Springfield', 6, 4); -- and more . . .
所有这三个表仍然至少处于 5NF。但是这个
(无效)更新现在将成功。
update states
set state = 'Wibble'
where state = 'Alabama';
这是一件坏事。
使用代理 ID 号使每个外键引用
具有与声明它们 on update cascade 相同的行为。恢复
on update restrict 的部分语义,你必须取
撤销更新权限的额外、不直观的步骤
引用的表。
几乎没有人正确理解这部分。
没有任何现实原则可以证明拆分主键的合理性
为了有一条您可以遵循的路径来恢复原件
关系。换句话说,没有关系原则
有理由改变这个......
城市
city_id 城市 County_id state_id
--
1 特洛伊 3 2
...到这个。
城市
city_id 城市 County_id
--
1 特洛伊 3
县
County_id 县 state_id
--
3 派克 1
不仅没有关系原则证明分裂是正当的
主键,它创建关系模型的问题之一
打算解决的数据。查找“IMS”,一个分层数据库
要求用户遵循路径的管理系统
数据文件。