【问题标题】:Update tags lists - or updating has_many relationships更新标签列表 - 或更新 has_many 关系
【发布时间】:2012-05-23 05:59:09
【问题描述】:

我经常遇到更新有很多关系的问题。 比如下面三个表:

  • 帖子
  • 标签
  • posts_tags

当用户创建新帖子时,他可以为帖子添加标签。帖子已保存,所选标签通过_posts_tags_附加到它。

当用户编辑帖子(也可能编辑标签列表也可能不编辑)并提交表单时,我必须更新帖子的标签列表。

解决方案可以是:更新帖子时,我从_posts_tags_中删除该帖子的所有标签,并插入提交的标签。

另一种解决方案是从数据库中获取帖子的所有标签,将列表与提交的标签进行比较,然后决定我们必须删除什么以及我们必须插入什么。

这两种解决方案都可能很耗时。
对于这个问题有什么更聪明的解决方案?

【问题讨论】:

  • 我有点累和昏昏欲睡,所以请耐心等待(可能读错了),但这不是级联的吗?
  • @Bono:不。问题不是如何在外部表中的相关记录之间级联更新,而是如何检测一组记录中的哪些记录在应用程序中被修改以反映数据库中的那些修改。
  • 在您发布的两个解决方案中,第一个通常更可取。使用索引的删除将比第二个所需的比较类型更快。至于寻找更“聪明”的解决方案,您是否应该考虑在这里申请KISS principle

标签: php mysql has-many has-many-through


【解决方案1】:

当文章被编辑并且标签未被编辑(可选)时,只需保存文章并且什么都不做。为什么?因为,在帖子、标签和帖子标签表中,您有一个自动增量列,它是您的主键。然后,这个数字列是各个表中的外键,即表如下所示:

帖子:id_post(PK)、post_title、post_content

标签:id_tag(PK)、tag_name

posts_tags:id_post_tag(PK)、id_post(FK)、id_tag(FK)

PK:主键 FK:外键

以这种格式保存数据后,您会发现无需更新任何依赖表,因为文本数据不再用于维护数据库架构和关系。这也加快了事务时间,因为数据库并不像 Bono 暗示的那样忙于任何级联作业。

然后为帖子中的所有标签运行一个简单的循环,以根据 post_tags 表中的 id_post 检查它们是否存在,如果未找到则插入它。在执行此循环时,您将在下面构建一个字符串:

接下来,运行以下查询:

delete from post_tags where id_post = {$id_post} and id_tag not in {$list_id_tags}

此操作通过最小化由添加和删除行引起的 IO 操作来最小化数据库服务器过载。您删除所有 post_tags 然后再次插入所有标签的情况会产生很大的 IO,而这种方法可以最大限度地减少这种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 2019-09-23
    • 2011-06-18
    相关资源
    最近更新 更多