8

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

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

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

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

当然我可以忽略所有这些麻烦,因为它已经工作了,但我真的很喜欢让事情尽可能高效。

4

4 回答 4

10

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

当我准备好处理提交的条目时,我首先进行查询以获取当前关联并调用该数组 $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
}

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

于 2012-06-05T15:42:59.267 回答
0

尝试在数据库中解决它,而不是在应用层通过使用ON UPDATE CASCADEON 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
);

希望这可以帮助。

于 2012-05-05T13:34:14.920 回答
0

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

于 2012-05-05T13:55:07.383 回答
0

如果您想保持当前的执行方式,但只是进行优化,您可以将查询包装在 IF 语句中。

像:

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

于 2012-05-06T13:47:57.570 回答