Database design 数据库模式问题

Database design 数据库模式问题,database-design,foreign-key-relationship,Database Design,Foreign Key Relationship,我正在为本地城市页面设计一个数据模型,更像是它的需求 SO4表:国家、州、城市、社区 现实生活中的关系是:国家拥有多个州,拥有多个城市,拥有多个街区 在数据模型中:我们是以相同的方式将它们与FK链接,还是将它们彼此链接?就像在每个表中一样,甚至会有一个国家ID、州ID、城市ID和邻里ID,所以每个都会相互连接?其他明智的做法是,从国家到邻里,我们需要加入两个其他表格之间 我需要维护更多关于城市IP地址、纬度/经度等的表。最接近行业标准的是:每个相关表通过外键链接到其直接父表: create ta

我正在为本地城市页面设计一个数据模型,更像是它的需求

SO4表:国家、州、城市、社区

现实生活中的关系是:国家拥有多个州,拥有多个城市,拥有多个街区

在数据模型中:我们是以相同的方式将它们与FK链接,还是将它们彼此链接?就像在每个表中一样,甚至会有一个国家ID、州ID、城市ID和邻里ID,所以每个都会相互连接?其他明智的做法是,从国家到邻里,我们需要加入两个其他表格之间


我需要维护更多关于城市IP地址、纬度/经度等的表。

最接近行业标准的是:每个相关表通过外键链接到其直接父表:

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不能用作城市的标识外键。所以城市必须参照国家。州可以是城市的可选查找

虽然我认为大多数国家都有一些类似的子部门,比如县或部门。甚至像利希滕斯坦和圣马力诺这样的微型国家也有市政当局(摩纳哥只有一个)。也许唯一没有的国家是梵蒂冈城。因此,仔细考虑是否要构造你的数据模型来支持一个或两个边缘情况,或者通过注入诸如“罗马教廷”之类的例外的人工“状态”来掩盖数据。这两种方法都不完全令人满意

“所有这些字段都将被删除 自动完成字段,因此不确定是否 这改变了中的表结构 反正?”

没什么区别

“但谁知道,几个月后我们 可能会发现一些很酷的功能 可能需要国家来匹配 邻里也一样。”

是的,但你也可以不这样做。XP有一个强大的原理叫做。基本上,不要做太多的工作,不要为了一些可能永远不会出现的假定的未来需求而使设计复杂化


如果它真的到达了,那么第一个解决方案就是通过中间表(或者表,如果您不使用STATE作为城市的引用)连接邻居和国家。仅当该查询的性能非常糟糕时!如果你考虑调整数据模型,它会顽强地抵制调优。 这个系统是全球设计的。因此,它将维护每个国家、每个城市、每个州和每个社区。当然,我们只有国家/城市的数据。邻居数据将由用户输入,因为这是一个用户内容站点。因此,最终会有数以千万计的居民区。目前没有将国家与邻里匹配的业务要求。这是一个有邻里关系的城市,如果存在邻里关系,也可能是一个有邻里关系的国家。但谁知道呢,几个月后我们可能会发现一些很酷的功能,可能需要国家/地区与邻近地区进行匹配。我不知道这是否重要,但所有这些字段都将是自动完成的字段,所以不确定这是否会改变表的结构?bt:感谢您的反馈和示例模型。我在示例行业代码中看到的问题是:虽然不是所有国家都有州,但州应该是可选的。然后一个国家将与城市直接相连。