有一个行业标准最接近的事是这样的:每个从属表是由外键链接其直接父:
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