2016-02-26 125 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」,這是一個分層數據庫管理系統,需要用戶按照路徑通過 數據文件。