我正在为本地城市页面设计数据模型,更像是对它的要求。
所以4个表:国家,州,城市,邻居。
现实生活关系是:国家拥有多个州,拥有多个城市,这些城市拥有多个社区。 p>
在数据模型中:我们是否以相同的方式将这些链接与FK或每个链接?就像在每个表中一样,甚至会有一个国家ID,州ID,城市ID和NeighbourhoodID,所以每个都与每个?其他明智的做法是从国家到达邻居我们需要加入其他两个表格吗?
我需要为城市的IP地址,纬度/经度等维护更多的表格。
答案 0 :(得分:5)
与行业标准最接近的是:每个从属表都通过外键链接到其直接父级:
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。 STATE可以是CITY上的可选查找。
虽然我认为大多数国家都有一些等同的细分,例如县或部门。甚至像利希滕斯坦和圣马力诺这样的微观状态也有市政当局(摩纳哥只有一个)。也许唯一没有的国家是梵蒂冈城。因此,请仔细考虑是否构建数据模型以支持一个或两个边缘情况,或者通过为诸如罗马教廷等例外注入人为的“状态”来挖掘数据。这两种方法都不完全令人满意。
“所有这些领域都将是 自动完成字段所以不确定是否 改变了表格结构 吗?“
没有任何区别。
“但谁知道,几个月后我们 可能会发现一些很酷的功能 可能需要国家匹配 邻居也是。“
是的但是你可能不会。 XP有一个强大的原则叫YAGNI - You're aren't gonna need it。基本上,为了一些可能永远不会到来的假定未来要求,不要做很多工作并使设计复杂化。
如果它确实到达那么第一个解决方案是通过中间表(或表,如果你不使用STATE作为CITY的引用)加入NEIGHBORHOOD和COUNTRY。只有当该查询的性能是Teh Suck时!如果你考虑调整数据模型,它就会顽固地抵制调整。