【问题标题】:Database structure for tags system标签系统的数据库结构
【发布时间】:2023-12-13 14:57:01
【问题描述】:

我正在制作一个简单的 PHP 论坛,标签是在主题旁边创建的。

表格如下所示:

  CREATE TABLE IF NOT EXISTS `topic` (
  `topic_id ` int(100) NOT NULL AUTO_INCREMENT,
  `topic_head` varchar(5) NOT NULL,
  `topic_body` varchar(20) NOT NULL,
  `topic_tag` varchar(20) NOT NULL,
  `topic_date` varchar(20) NOT NULL,
  `topic_owner` varchar(20) NOT NULL,
  PRIMARY KEY (`topic_id`)
  ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;

特别是对于标签,我将以如下形式执行选择查询:

$tags = mysql_query("SELECT DISTINCT topic_tags
                       FROM forum_topics")
                       while($tags = mysql_fetch_assoc($tags){   
                       $split_tags  = "$tags";
                       $pieces = explode(",", $split_tags);

目前,topic_tags 的格式为tag1,tag2,tag3,tag4 我怎样才能让每个主题标签都与每个主题相关联?

【问题讨论】:

  • 你能澄清你的问题吗,你想做什么?

标签: php mysql database optimization normalization


【解决方案1】:

如果我理解正确,您想要的是另一个标签表,然后是第三个表来存储关系。所以:

CREATE TABLE `tags` (
  `t_id` int(11) NOT NULL AUTO_INCREMENT,
  `t_text` varchar(150) NOT NULL,
  `t_datetime` datetime NOT NULL,
  PRIMARY KEY (`t_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

CREATE TABLE `tag_pairs` (
  `tp_id` int(11) NOT NULL AUTO_INCREMENT,
  `tp_topic_id` int(11) NOT NULL,
  `tp_tag_id` int(11) NOT NULL,
  `tp_datetime` datetime NOT NULL,
  PRIMARY KEY (`tp_id`),
  FOREIGN KEY (`tp_topic_id`) REFERENCES topic('topic_id'), 
  FOREIGN KEY (`tp_tag_id`) REFERENCES tags('t_id') 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

然后,根据 ID ($THIS_ID) 获取主题的标签:

$query = mysql_query("
  SELECT tags.t_text 
  FROM tags, tag_pairs, topic 
  WHERE topic.topic_id = '$THIS_ID'
  AND tag_pairs.tp_topic_id = topic.topic_id 
  AND tag_pairs.tp_tag_id = tags.t_id 
 ");

【讨论】:

  • 是的,还有变量清理(或 PDO)。我只是想弄清楚它的要点。
  • 我只是觉得 FK 约束是规范化的一部分,而您的回答并没有达到这一点。
  • 如果我将t_id 添加到我的主题表并为您建议的标签创建一个新表怎么办。从而消除你的第二张桌子。?
  • 如果每个主题只有一个标签,这将起作用。你不想每个主题有多个标签吗?
【解决方案2】:

只需调用列:idheadbodytag_id (FK)dateuser_id (FK)

这更容易理解,也更容易使用。让我解释一下:

现在您使用的列是:topic_id,但它应该是:topic.id。你怎么得到这个?只需使用tablename + column。因此,当表名为 topics 并且您有一个名为 id 的列时,您可以通过说:topics.id 来使用它。在上面来自 da5id 的答案中,我可以看到他正在使用topics.topic_id,是不是有点矫枉过正? ;)

另外,请阅读这篇关于database normal form 3 的文章,并使用database+3nf 自己搜索一下

【讨论】:

  • "topics.topic_id' 来自 OP 的表模式 :)