1

仍在尝试开始使用数据库,每天都会遇到问题!

我有一张“歌曲”表,其中包含有关艺术家/曲目的信息:

CREATE TABLE songs (
    song_id INT AUTO_INCREMENT PRIMARY KEY, 
    artist_name varchar(100) DEFAULT NULL,
    song_name varchar(100) DEFAULT NULL,
    tag_fk SMALLINT,
    FOREIGN KEY (tag_fk) REFERENCES tags(tag_id) ON DELETE SET NULL ON UPDATE CASCADE,
) ENGINE = 'InnoDB';

CREATE TABLE tags (
    tag_id SMALLINT AUTO_INCREMENT PRIMARY KEY,
    tag_name varchar(255) UNIQUE
) ENGINE = 'InnoDB';

现在我在“歌曲”中有一个引用“tags.tag_id”的外键,“tags.tag_name”稍后将包含“lovesong”、“melancholic”等标签。现在在某些情况下,一首歌可以有多个标签,所以如果它是一首忧郁的情歌,它应该有两个标签。虽然我刚刚注意到我不能将两个 SMALLINT 添加到 tag_fk 以逗号分隔,但它只允许每行一个 SMALLINT。

我想我可以在 'tag.tag_name' 中添加一个包含'lovesong;melancholic' 的新行,然后在 php 中处理它,用 ';' 拆分它,但这是一个不那么性感的问题解决方案,特别是因为数据是由一个程序添加的,我也必须处理对字符串进行排序,所以我不会得到重复的标签,比如“lovesong;melancholic”和“melancholic;lovesong”,这基本上是一样的。

这个问题一般是怎么解决的?如果我用 varchar 列 'songs.tag' 替换 'songs.tag_fk' 而不是我会有大量重复数据,因为数据库中会有很多“Lovesongs”和“Melancholic”歌曲,所以一个外键解决方案可能是最好的。

我还考虑过添加 'songs.tags_fk' 和 'songs.tags_fk2' 但这也是一个肮脏的 hack。特别是如果某些歌曲开始有超过 2、3、4 个标签。

处理它的最佳方法是什么?

4

2 回答 2

2

听起来像是多对多的关系。您需要第三个表来链接两者。这样一首歌可以有很多标签,一个标签可以分配给很多歌曲。

http://www.phpknowhow.com/mysql/many-to-many-relationships/

于 2012-09-20T13:32:28.217 回答
1

您想要的是多对多表关系。为此,您可以创建第三个表,其中包含 song_id 和 tag_id 的外键。

CREATE TABLE Song_Tag_Xref (
    FOREIGN KEY (tag_id) REFERENCES tags(tag_id),
    FOREIGN KEY (song_id) REFERENCES songs(song_id),
) ENGINE = 'InnoDB';

然后,您可以通过执行以下操作获取歌曲的所有标签:

select tags.tag_name 
from songs, song_tag_xref, tags 
where songs.song_id = song_tag_xref.song_id 
and song_tag_xref.tag_id = tags.tag_id
and songs.artist_name like 'Bob Marley'
于 2012-09-20T13:36:40.860 回答