假设我们有一个国家表和一个城市表。一个国家当然可以有许多城市,但是一个城市只能在一个国家中,因此一对多关系在直觉上是有意义的:
countries
| id | name |
| 1 | Lorwick |
| 2 | Belmead |
cities
| id | country | name |
| 1 | 1 | Marblecrest |
| 2 | 1 | Westacre |
| 3 | 2 | Belcoast |
| 4 | 1 | Rosemarsh |
| 5 | 2 | Vertston |
但是,除了我们的一对多关系之外,我们还要描述国家首都的一对一关系。如果重要的话,请假设资本可能会定期发生变化,因此,城市会随意出现和消失,并且城市可能会切换国家。关键是,该数据不稳定。
我看到几个选择:
将一个int列
capital
添加到countries
,该列不能为null。优点:永远只是一个城市;缺点:与城市无关,在该国没有强制执行的城市,甚至没有该城市存在。在
capital
中添加一个布尔列cities
,如果该列为true,则表示城市是相关国家的首都。优点:与相关城市直接相关,没有重复的列表示等级;缺点:可以肯定的是,这归一化程度很差,因为没有什么可以阻止某个国家的零或多个“资本”。创建具有列
capitals
和country
的附加表city
,并且在两列上(或至少在city
上)具有唯一约束。优点:感觉更清洁,易于在countries
或cities
上加入;缺点:仍然不能确保城市在乡村中,或者存在。代表这种关系的最规范和/或最佳方法是什么?有什么方法可以确保每个国家只有一个实际上存在并居住在该国家内部的资本?我想这是不可能的,在这种情况下,如何才能最大程度地减少客户端代码的问题?
我目前正在使用SQLite,但是无论基础数据库如何,我都对通用答案感兴趣。
我做了一些挖掘,发现Indicating primary/default record in database,但我认为这并不能真正回答我的问题。
PS:如果没有首都(可能没有城市!)并没有那么糟糕,但是如果有多个首都,那将会很糟糕。
最佳答案
为了清楚和简单起见,我将布尔值IsCapital列添加到citys表。然后添加一个触发器,以在记录上将IsCapital设置为true时,设置所有其他城市(共享更新记录的国家/地区)IsCapital = false。这将解决您的大部分顾虑。确保不可能每个国家只有一个资本的一种情况是,您可以确保有0或1,但是由于citys表对国家/地区有FK约束,因此总会有一个时间点插入的国家将没有可以设置为国会大厦的城市。
FWIW,我认为应该将逻辑留给应用程序,并将引用完整性留给数据库。
关于sqlite - 在一对多表中指示“规范”记录,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11980529/