规范化数据库表“标签”

时间:2011-10-19 19:22:10

标签: php mysql

我有一个名为标记的表格,列idvid_idname其中id是使用md5(uniqid());生成的随机ID vid_id是标记与之关联的视频的ID,name是标记名称。如果视频有5个标签,则它们都存储在标签表中。我最近意识到这是一个糟糕的表设计,因为我有许多重复的标签。我创建了另一个表 tag_map 。它有三列idvid_idtag_id。我想基本上实现这里显示的'toxi'解决方案http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html

我想要做的是以某种方式将数据从标记传输到 tag_map ,删除标记中的vid_id列并删除任何额外的标记中的条目,因此每个tag_map条目仅映射到一个标记条目。有人知道这样做的有效方法吗?我一直在想:

$sql = 'SELECT * FROM tags';
$stmt3 = $conn->prepare($sql);
$result=$stmt3->execute();
while ($row = $stmt3->fetch(PDO::FETCH_ASSOC)) {

$id=md5(uniqid());

    $sql = 'INSERT INTO tag_map VALUES (?,?,?)';
$insert = $conn->prepare($sql);
$result=$insert->execute(array($id,$row['vid_id'],$row['id']));
}

但是当我想到如何删除表标签中的额外标签并将每个tag_map条目映射到一个标签条目时,我感到困惑。任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:2)

您可以做的一件事是将vid_idtag_id对设置为新tag_map表中的主键。这样,当您浏览上面列出的算法时,将不会创建重复的地图条目,但您仍然会为每个标记创建一个。然后,您可以运行查询以删除tags表中的重复项,如下所示:

DELETE FROM TAGS WHERE ID NOT IN (SELECT tag_id FROM TAG_MAP)

答案 1 :(得分:2)

如果我理解你的帖子,那么你所追求的是一个“连接表”或“连接表”。 (重新阅读,是的,这是你所指的“Toxi”解决方案。不知道它在哪里得到“Toxi”这个名字,但无论如何。)

http://en.wikipedia.org/wiki/Junction_table

您想拥有一个只有一行给定视频的表格。另一个表,每个标签只有一行。然后你需要在它们之间的第三个表,每个视频和标签的组合有一行。这样,您可以在第三个联接表中查询与给定标记匹配的所有视频,或与给定视频匹配的所有标记。

我会创建一个新表“tag”和一个表“video_tag”。

foreach ( video_record in the video table ) {
    existingTags = read in list of tags for video_record from existing_tags_table
    foreach ( tag in existingTags ) {
        newTag = read tag from new tag table
        if ( newTag == null ) {
            save tag in new table
            newTag.name = existing tag name
            newTag.id = id from save procedure above
        }
        save entry in video_tag( video.id, newTag.id )
    }
}

然后删除旧标签表。如果需要,可以重新命名新的标记表。