假设我有一个artist
表,如下所示:
Id|名称
1|John Coltran
2|斯普林斯汀
和song
表,如下所示:
Id|标题
1|雨中歌唱
2|含羞草
现在一个艺术家可以写不止一首歌,一首歌也可以由不止一个艺术家写。我们有多对多的关系。我们需要一个关联表!
如何设计关联表的主键?
一种方法是定义两个外键的组合键,如下所示:
CREATE TABLE artist_song_map(
artist_id INTEGER,
song_id INTEGER,
PRIMARY KEY(artist_id, song_id),
FOREIGN KEY(artist_id) REFERENCES artist(id),
FOREIGN KEY(song_id) REFERENCES song(id)
)
另一种方法是使用合成主键,并对两个外键的元组施加唯一约束:
CREATE TABLE artist_song_map(
id INTEGER PRIMARY KEY AUTOINCREMENT,
artist_id INTEGER,
song_id INTEGER,
UNIQUE(artist_id, song_id),
FOREIGN KEY(artist_id) REFERENCES artist(id),
FOREIGN KEY(song_id) REFERENCES song(id)
)
哪种设计选择更好?
4条答案
按热度按时间ia2d9nvy1#
除非将表定义为
WITHOUT ROWID
,否则两个查询将创建相同的表。第二种方法中的列
id
只为将以这两种方法之一创建的列rowid
添加别名。由于这是一个桥接表,您只需要将列
artist_id
和song_id
的组合定义为UNIQUE
。如果要使用其他表(如
playlist
表)扩展设计,则必须决定如何将其链接到现有表:artist_song_map
中没有id
列,则将playlist
链接到song
和artist
,就像您对artist_song_map
所做的那样。artist_song_map
中有id
列,则可以将playlist
直接链接到该id
。我建议您不仅根据这3个表(
song
、artist
和artist_song_map
)做出决定,而且还根据您计划添加的表做出决定。cyvaqqii2#
从逻辑上讲,这两种设计是相同的。但从管理层面看,身份设计更有效率。更少的磁盘碎片和未来的重新设计或维护将更容易。
bprjcwpo3#
桥接表通常不需要ID(AUTO_INCREMNT)来标识行。
链接栏(外键)是要点,因为它将艺术家链接到一首或多首歌曲)
只有当您需要该桥的特殊属性,或者您想引用该桥接表的一行并且不想有两个链接列时,您才会使用这样的ID字段,但正如我所说的,通常您永远不需要它
bvhaajcl4#
虽然通常差异不大,但复合/复合外键设计听起来更自然。单独的主键和关联的索引会占用数据库中的额外空间。此外,如果使用复合主键,则可以将表声明为没有ROWID。根据官方的docs,“在某些情况下,没有ROWID的表可以使用大约一半的磁盘空间量,并且可以操作快近两倍**”。