简体   繁体   English

设计关联表中的主键

[英]Designing the primary key in associative table

Suppose I have an artist table like:假设我有一个artist表,如:

id ID name姓名
1 1 John Coltrane约翰·科尔特兰
2 2 Springsteen斯普林斯汀

and a song table like:和一个song表,如:

id ID title标题
1 1 Singing in the rain在雨中唱歌
2 2 Mimosa含羞草

Now an artist can write more than one song, and a song can be written by more than one artist.现在一个艺术家可以写不止一首歌,而一首歌可以由不止一个艺术家写。 We have a many-to-many relation.我们有一个多对多的关系。 We need an associative table!我们需要一个关联表!

How to design the primary key of the associative table?如何设计关联表的主键?

One way would be to define a composite key of the two foreign keys, like this:一种方法是定义两个外键的复合键,如下所示:

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)
)

Another way would be to have a synthetic primary key, and impose an unique constraint on the tuple of the two foreign keys:另一种方法是使用合成主键,并对两个外键的元组施加唯一约束:

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)
)

Which design choice is better?哪种设计选择更好?

Logically the both design is the same.从逻辑上讲,两者的设计是相同的。 But from administration aspect the identity design is more efficient.但从管理方面来看,身份设计更有效。 Less disk fragmentation and future redesign or maintenance will be easier.更少的磁盘碎片和未来的重新设计或维护会更容易。

Unless you define the table as WITHOUT ROWID both queries will create the same table.除非您将表定义为WITHOUT ROWID ,否则两个查询都将创建同一个表。

The column id in your 2nd way adds nothing but an alias for the column rowid that will be created in any of the 2 ways.第二种方式中的列id只添加了列rowid的别名,该列将以两种方式中的任何一种方式创建。

Since this is a bridge table, you only need to define the combination of the columns artist_id and song_id as UNIQUE .由于这是一个桥表,您只需要将列artist_idsong_id的组合定义为UNIQUE

If you want to extend your design with other tables, like a playlist table, you will have to decide how it will be linked to the existing tables:如果您想使用其他表格扩展您的设计,例如playlist表格,您必须决定如何将其链接到现有表格:

  • If there is no id column in artist_song_map then you will link playlist to song and artist , just like you did with artist_song_map .如果在artist_song_map中没有id列,那么您将playlist链接到songartist ,就像您对artist_song_map所做的那样。
  • If there is an id column in artist_song_map then you can link playlist directly to that id .如果在artist_song_map中有一个id列,那么您可以将playlist直接链接到该id

I suggest that you base your decision not only on these 3 tables ( song , artist and artist_song_map ), but also on the tables that you plan to add.我建议您不仅要根据这 3 个表( songartistartist_song_map )做出决定,还要根据您计划添加的表来做决定。

Bridge tables normally don't require a ID(auto_inCREMNT) to identify the rows.桥接表通常不需要 ID(auto_inCREMNT) 来识别行。

The linking columns(foreign key) are the main point, as thea link artists to a 8or songs)链接栏(外键)是重点,因为将艺术家链接到 8 或歌曲)

only when you need special attributes to that bridge or you want to reference a row of that bridge table and don't want to have ttwo linking columns, then you would use such an ID field, but as i said normally you never need it只有当您需要该桥的特殊属性或者您想要引用该桥表的一行并且不想有两个链接列时,您才会使用这样的 ID 字段,但正如我所说的,您通常不需要它

While, generally, the differences are minor, the composite/compound foreign key design sounds more natural.虽然通常差异很小,但复合/复合外键设计听起来更自然。 A separate primary key together with the associated index take additional space in the database.单独的主键与关联的索引一起占用数据库中的额外空间。 Further, if you use a composite primary key, you can declare the table as WITHOUT ROWID.此外,如果您使用复合主键,您可以将表声明为 WITHOUT ROWID。 According to the official docs , " in some cases , a WITHOUT ROWID table can use about half the amount of disk space and can operate nearly twice as fast ".根据官方文档,“在某些情况下,一个 WITHOUT ROWID 表可以使用大约一半的磁盘空间,并且运行速度几乎是两倍”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM