有一個行業標準最接近的事是這樣的:每個從屬表是由外鍵鏈接其直接父:
create table country
(country_id number not null
, country_name varchar2(30)
, constraint country_pk primary key (country_id)
)
/
create table state
(state_id number not null
, state_name varchar2(30)
, country_id number not null
, constraint state_pk primary key (state_id)
, constraint state_country_fk foreign key (country_id)
references country(country_id)
)
/
create table city
(city_id number not null
, city_name varchar2(30)
, state_id number not null
, constraint city_pk primary key (city_id)
, constraint city_state_fk foreign key (state_id)
references state(state_id)
)
/
create table neighbourhood
(neighbourhood_id number not null
, neighbourhood_name varchar2(30)
, city_id number not null
, constraint neighbourhood_pk primary key (neighbourhood_id)
, constraint neighbourhood_city_fk foreign key (city_id)
references city(city_id)
)
/
的另一種方法,這已經在很大程度上失寵,是定義子表爲化合物鍵,包括直接父表的鍵的主鍵:
create table state
(country_id number not null
, state_id number not null
, state_name varchar2(30)
, constraint state_pk primary key (country_id, state_id)
, constraint state_country_fk foreign key (country_id)
references country(country_id)
)
/
create table city
(country_id number not null
, state_id number not null
, city_id number not null
, city_name varchar2(30)
, constraint city_pk primary key (country_id, state_id, city_id)
, constraint city_state_fk foreign key (country_id, state_id)
references state(country_id, state_id)
)
/
create table neighbourhood
(country_id number not null
, state_id number not null
, city_id number not null
, neighbourhood_id number not null
, neighbourhood_name varchar2(30)
, constraint neighbourhood_pk primary key (country_id, state_id, city_id, neighbourhood_id)
, constraint neighbourhood_city_fk foreign key (country_id, state_id, city_id)
references city(country_id, state_id, city_id)
)
/
這種方法不推薦使用,因爲在短期內會造成非常笨拙的連接,並且從長遠來看,當密鑰更改時會產生可怕的混亂。主鍵不應該改變,但複合它們會產生意義。因此,當系統的數據發生變化時(比如說有一個州邊界重新組織),對整個城市的改變必須與鄰居表和其他任何兒童級聯。呸。
你的建議是這樣的替代版本:
create table state
(state_id number not null
, state_name varchar2(30)
, country_id number not null
, constraint state_pk primary key (state_id)
, constraint state_country_fk foreign key (country_id)
references country(country_id)
)
/
create table city
(city_id number not null
, city_name varchar2(30)
, country_id number not null
, state_id number not null
, constraint city_pk primary key (city_id)
, constraint city_country_fk foreign key (country_id)
references country(country_id)
, constraint city_state_fk foreign key (state_id)
references state(state_id)
)
/
create table neighbourhood
(neighbourhood_id number not null
, neighbourhood_name varchar2(30)
, country_id number not null
, state_id number not null
, city_id number not null
, constraint neighbourhood_pk primary key (neighbourhood_id)
, constraint neighbourhood_country_fk foreign key (country_id)
references country(country_id)
, constraint neighbourhood_state_fk foreign key (state_id)
references state(state_id)
, constraint neighbourhood_city_fk foreign key (city_id)
references city(city_id)
)
/
它避免了複合鍵,但你仍然有級聯數據問題。它還通過爲不存在的關係引入外鍵來違反關係實踐(鄰里關係和國家之間沒有直接關係,它通過中間關係暗示)。
正如您指出的那樣,這對於運行想要返回給定國家的鄰域的查詢非常有幫助。我曾經在一個有用的系統上工作(實際上它使用了繼承的複合鍵,但原理是一樣的)。但是,這是一個非常專業的數據倉庫,即使這樣,我運行的查詢是管理員/開發人員查詢,而不是應用程序查詢。除非您處理大量數據(數百萬個社區),否則我認爲跳過幾個連接所帶來的性能提升並不值得管理這些額外列的開銷。
總之,使用第一種方法:它很整齊,它是標準的。
編輯
「國家應該是可選的,雖然因爲 並非所有國家都有的狀態。然後, 國家將直接與城市 連接。」
如果屬實,那會改變一切。顯然,STATE不能用作CITY的識別外鍵。所以CITY必須引用COUNTRY。狀態可以是CITY上的可選查詢。
雖然我認爲大多數國家確實有一些等同的細分,如縣或部門。即使像列支敦士登和聖馬力諾這樣的大國都有自治市(摩納哥只有一個)。也許唯一不是梵蒂岡的國家。因此,請仔細考慮是否構建數據模型以支持一個或兩個邊緣案例,或者通過爲教廷等例外注入人造「國家」來挖掘數據。這兩種方法都不完全令人滿意。
「所有這些領域將是 自動完成字段,以便不知道 在 改變表結構呢?」
沒有區別。
「但是誰知道,幾個月後我們 可能會發現一些很酷的功能, 可能需要國家以配合 街區了。」
是的,但你可能不會。 XP有一個強大的原理叫做YAGNI - You're aren't gonna need it。基本上,爲了某些可能永遠不會到來的假定未來要求,不要做大量工作並使設計複雜化。
如果它確實到達,那麼第一個解決方案是通過中間表(或表,如果你沒有使用STATE作爲CITY的引用)來加入NEIGHBORHOOD和COUNTRY。只有該查詢的性能是Teh Suck!如果你考慮調整數據模型,它會固執地抵制調整。
那麼這個系統是全球設計的。所以它會維護每個國家,每個城市,每個州和每個社區。當然,我們只有國家/城市的數據。由於這是一個用戶內容網站,所以鄰居數據將被用戶推定。所以最終是的,會有數千萬的社區。 目前沒有匹配的國家與鄰里業務要求。這是與鄰居的城市,也許與鄰居州,如果存在。但是誰知道呢,幾個月後,我們可能會發現一些很酷的功能,可能需要國家與社區相匹配。 – Thomas 2010-06-18 02:23:27
我不知道它是否重要,但所有這些領域將自動完成領域,所以不知道是否改變了表結構呢? bt:感謝您的反饋和示例模型。 – Thomas 2010-06-18 02:25:09
我在示例行業代碼中看到的問題是:狀態應該是可選的,但不是所有國家都有狀態。然後一個國家將直接與城市連接。 – Thomas 2010-06-18 02:26:55