【问题标题】:PHP update MYSQL many-to-many relationPHP更新MYSQL多对多关系
【发布时间】:2012-05-05 13:15:27
【问题描述】:

我有一个多对多关系,用 MySQL 中的关联表实现。我有一张儿童桌和一张父母桌。一个孩子可以有多个父母,他们的 ID 保存在 parent_child_link 关联表中。

子项可以通过 HTML 表单更新,父项在 HTML 多选中。现在我需要更新数据库中的记录,但是我的解决方案效率不是很高。这是我所做的伪代码:

  1. 更新child_id=x的子信息
  2. 删除 parent_child_link 中 child_id=x 的所有当前关联
  3. 插入新的关联

这个解决方案效果很好,但是当父母没有改变时,例如只更改了孩子的名字,然后执行了 2 个不必要的查询。我怎样才能避免那些不必要的查询?有没有办法检查多选中的父母是否没有改变?

当然,我可以忽略所有这些麻烦,因为它已经有效,但我真的希望尽可能保持高效。

【问题讨论】:

    标签: php mysql many-to-many


    【解决方案1】:

    我有同样的问题,并在阅读时找到了解决方案。

    当我准备好处理提交的条目时,我首先进行查询以获取当前关联并调用该数组 $original_list。提交的列表我将调用$submitted_list。

    $original_list = array(3,5,7);
    $submitted_list = array(1,2,3);
    

    然后我只需要弄清楚 1)要删除哪些项目(不再存在)和 2)要添加哪些项目(新关联)。两个列表中的项目都不会被触及。

    $delete_list = array_diff($original_list, $submitted_list);
    $insert_list = array_diff($submitted_list, $original_list);
    
    foreach($delete_list as $item) {
        // delete $item from DB
    }
    
    foreach($insert_list as $item) {
        // insert item in db
    }
    

    很想知道其他人是否认为这是一个有效的解决方案。

    【讨论】:

    • 是的,这就是我过去做过类似事情的方式。通常我会使用 delte -> insert 方法,但如果孩子的 ID 在其他地方被引用,这可能会出现问题,例如,如果您向产品添加多个价格条目并且价格 ID 是从购物车中引用的.当价格在技术上没有改变时,不能去改变 ID。
    【解决方案2】:

    尝试在数据库中解决它,而不是在应用层通过在子表的定义中使用ON UPDATE CASCADE和ON DELETE CASCADE。

    一个来自 MySQL 站点的稍微修改的示例:

    CREATE TABLE parent (id INT NOT NULL,
                         PRIMARY KEY (id)
    ) ENGINE=INNODB;
    
    CREATE TABLE child (id INT, parent_id INT,
                        INDEX par_ind (parent_id),
                        FOREIGN KEY (parent_id) REFERENCES parent(id)
                          ON DELETE CASCADE ON UPDATE CASCADE
    ) ENGINE=INNODB;
    

    在此处查看文档:http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html

    编辑:对于您的多对多关系,您可以使用以下内容:

    CREATE TABLE parent_child_link (
                        parent_id INT NOT NULL,
                        child_id INT NOT NULL,
                        PRIMARY KEY(parent_id, child_id),
                        FOREIGN KEY (parent_id) REFERENCES parent(id)
                          ON DELETE CASCADE ON UPDATE CASCADE,
                        FOREIGN KEY (child_id) REFERENCES child(id)
                          ON DELETE CASCADE ON UPDATE CASCADE
    );
    

    希望这会有所帮助。

    【讨论】:

    • 这是一对一的; OP 与数据透视表具有多对多关系。
    • 我很想将它移到应用层之外,但我看不出您的引用解决方案将如何解决我的问题。据我设法分析它,在删除孩子或父母(摆脱链接)时会很有用。
    【解决方案3】:

    您的解决方案很好。
    在您的情况下,您可以通过查询来检索父母并检查多选数据是否发生任何更改来“优化”该过程。
    然后,您只需在需要时执行两个删除和插入查询。对应的是,当您实际更改父母时,将有 3 个查询而不是 2 个。
    所以你应该问你是否要经常修改父母。在这种情况下,您应该坚持原来的解决方案以避免额外的选择查询。
    如果您认为父母不会经常更新,那么您可以使用上述解决方案。仅更新子信息时,仅执行一个查询。当您还更新父母时,将执行 3 次查询。
    当您使用第二种解决方案时,也可以优化删除和插入查询以仅执行所需的操作(仅删除不再是其父级的父级,并仅插入新的父级链接)。
    PHP 数组函数对此很有帮助。

    【讨论】:

      【解决方案4】:

      如果您想保持目前的做法,但只是优化,您可以将查询包装在 IF 语句中。

      喜欢:

      if ( isset ( $parent_name_change )){ // run query }

      【讨论】:

        猜你喜欢
        • 2010-10-21
        • 2017-01-30
        • 2021-07-23
        • 1970-01-01
        • 2014-12-11
        • 2011-04-05
        • 1970-01-01
        相关资源
        最近更新 更多