[英]Designing the primary key in associative table
Suppose I have an artist
table like:假设我有一个
artist
表,如:
id ![]() |
name![]() |
---|---|
1 ![]() |
John Coltrane![]() |
2 ![]() |
Springsteen![]() |
and a song
table like:和一个
song
表,如:
id ![]() |
title![]() |
---|---|
1 ![]() |
Singing in the rain![]() |
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_id
和song_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
表格,您必须决定如何将其链接到现有表格:
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
链接到song
和artist
,就像您对artist_song_map
所做的那样。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 个表(
song
、 artist
和artist_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.