2016-02-26 87 views
0

我有5个表:数据库正常化困惑?

  1. tblProvince
  2. tblDivison
  3. tblDistrict
  4. tblCity
  5. tblconstituency

tblProvince

  • ID
  • 名称

TblDivision

  • ID
  • 名称
  • Province_id

tblDistrict

  • ID
  • 名称
  • Province_id
  • Division_id

tblCity

  • ID
  • 名称
  • Province_id
  • Division_id
  • District_id

TblConstituency

  • ID
  • 名称
  • Province_id
  • Division_id
  • District_id
  • City_id

这是存储数据的正确方法?增加区域的完整细节。

或者我应该保存以前区域的ID(比如城市是选区的容器)。存储选区的细节,我应该广告city_id。

这样的...

tblCity 
+-------------+ 
| ID   | 
+-------------+ 
| Name  | 
+-------------+ 
| Area  | 
+-------------+ 
| District_id | 
+-------------+ 

TblConstituency 
+-------------+ 
| ID   | 
+-------------+ 
| Name  | 
+-------------+ 
| Area  | 
+-------------+ 
| City_id  | 
+-------------+ 

,如果我想获得选区完整的细节我能得到城市的ID,并从城市的我能得到区,从区我能得到师等上。

但是,我觉得它是一个巨大的矫枉过正。每次我需要获取详细信息时,这将是一个长查询。

那么,最好的方法是什么?

上午:致歉说穷人的方式来描述我的问题。

+0

这个Area字段是做什么用的?您可能错过了由ID字段和AreaName字段组成的TblArea。你应该在TblProvince表中添加一个Area_Id –

回答

2

切勿存储两次相同的信息。这意味着您将不得不手动保持信息同步,并且同步困难并且容易出错。基本上,任何时候你有多个真相来源,都没有真相。

这里考虑您的表:

Division 
+-------------+ 
| ID   | 
+-------------+ 
| Name  | 
+-------------+ 
| Area  | 
+-------------+ 
| Province_id | 
+-------------+ 



District 
+-------------+ 
| ID   | 
+-------------+ 
| Name  | 
+-------------+ 
| Area  | 
+-------------+ 
| Province_id | 
+-------------+ 
| Division_id | 
+-------------+ 

Division已经存储Province_id。那么为什么District也需要存储它呢?如果District存储一个不同Province_id会发生什么情况比它对应的Division记录?哪一个是对的District

只是链接到直接父记录:

District 
+-------------+ 
| ID   | 
+-------------+ 
| Name  | 
+-------------+ 
| Area  | 
+-------------+ 
| Division_id | 
+-------------+ 

的信息,通过相对于Division表,已经存在,并且可以查询。 (基本上,这就是JOIN关键字的用途。)由于您已经拥有这些信息,因此无需重复。

0

只是为了澄清另一个答案并删除冗余,这可能会澄清各自的查询/连接。我重命名列,以确保上下文澄清,但可能会丢失你的“区” FIEL

tblProvince:  (ID, ProvinceName, Area) 
TblDivision:  (ID, DivisionName, ProvinceID) 
tblDistrict:  (ID, DistrictName, DivisionID) 
tblCity:   (ID, CityName, DistrictID) 
TblConstituency: (ID, ConstituencyName, CityID) 

select 
     Con.ConstituencyName, 
     City.CityName, 
     Dis.DistrictName, 
     Div.DivisionName, 
     Prov.ProvinceName, 
     Prov.Area 
    from 
     tblConstituency Con 
     JOIN tblCity City 
      on Con.CityID = City.ID 
      JOIN tblDistrict Dis 
       on City.DistrictID = Dis.ID 
       JOIN tblDivision Div 
        on Dis.DivisionID = Div.ID 
        JOIN tblProvince Prov 
        on Div.ProvinceID = Prov.ID 

的情况下,注意分层表示的加入其中,从一个表到下一个。你看到表格的直接相关性。然后,如果您正在查找特定区域,则只需应用WHERE子句。

1

通过BCNF规范化基于功能依赖性。什么 是像这样的数据的功能依赖?什么是 候选键?

 
Cities 
State  County  City 
-- 
Alabama  Pike   Troy 
Arkansas Pike   Delight 
Florida  Bay   Springfield 
Maine  Penobscot Springfield 

这里只有一个(简单)函数依赖,只有一个 候选键。唯一的FD是州,县,市 - >州,县, 市。唯一的候选关键是{州,县,城市}。这个关系 至少在5NF。

无法改善这种关系,但你可以提高的 数据库。该数据库并不知道阿拉巴马州没有任何名为“Los Angeles”的县。所以它会让你插入这个无效的行。

 
Cities 
State  County  City 
-- 
Alabama  Los Angeles Troy 

要解决问题,添加包含所有有效 县的关系,并设置一个外键引用。

 
Counties 
State 
-- 
Alabama  Autauga 
Alabama  Baldwin 
... 
Alabama  Pike 
... 
California Los Angeles 
... 

的关系,“县”为所有键,它没有非黄金 属性。 “县”也至少在5NF。

数据库仍然不知道它不应该允许这样的行。

 
Cities 
State County City 
-- 
Wales Pike Troy 

有没有名为威尔士在美国的状态。解决这个问题的方法与上一个问题相同。

 
States 
-- 
Alabama 
Arkansas 
... 
California 
... 

并设置县的国家的外键引用。

下面是它在标准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 . . . 

现在你会发现,这是不可能插入无效元组 {特洛伊,洛杉矶,阿拉巴马}和{特洛伊,派克,威尔士}。

使用代理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的语义,必须采取 额外的,不直观的步骤来撤销对 引用表的更新权限。

差不多没有人获得该部分的权利。


有这证明,才能有你可以跟着恢复原始 关系的路径分离主键 没有realtional原则。换句话说,没有关系原则 有理由改变这个...

 
Cities 
city_id city county_id state_id 
-- 
1  Troy 3   2 

...这一点。

 
Cities 
city_id city county_id 
-- 
1  Troy 3 
 
Counties 
county_id county state_id 
-- 
3   Pike 1 

不仅有证明有理由分裂 主键没有关系的原则,它产生的问题一个旨在解决 数据的关系模型。查找“IMS”,这是一个分层数据库管理系统,需要用户按照路径通过 数据文件。