我有一个多对多的关系,用MySQL中的关联表实现。我有一张儿童餐桌和一张父母餐桌。子项可以有多个父项,保存在parent_child_link关联表中,并带有其ID。
可以通过HTML表单更新子项,父项是HTML多选。现在我需要更新数据库中的记录,但我的解决方案效率不高。这是伪代码我做的:
此解决方案效果很好,但是当父母没有改变时,例如只更改了孩子的名字,然后执行了2个不必要的查询。如何避免那些不必要的查询?有没有办法检查多选中的父母是否没有改变?
当然,我可以忽略所有这些麻烦,因为它已经有效,但我真的希望尽可能保持高效。
答案 0 :(得分:8)
我有同样的问题,在我阅读时想出了我的解决方案。
当我准备处理提交的条目时,我首先进行查询以获取当前关联并调用该数组$ 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
}
很想知道其他人是否认为这是一个有效的解决方案。
答案 1 :(得分:0)
尝试在子表的定义中使用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
);
希望这有帮助。
答案 2 :(得分:0)
你的解决方案没问题
在你的情况下,你可以"优化"通过进行查询以检索父项并使用多选数据检查是否发生任何更改的过程
然后,如果需要,您只执行两次删除和插入查询。对应的是,当你实际更改父母时,则会有3个查询而不是2
所以你应该问你是否要经常修改父母。在这种情况下,您应该坚持使用原始解决方案,以避免额外的选择查询
如果您认为父母经常不会更新,那么您可以使用上述解决方案。仅更新子信息时,仅执行一个查询。当您还更新父母时,将执行3个查询
当你使用第二个解决方案时,删除和插入查询也可以进行优化,只执行所需的操作(只删除不再是父母的父项,只插入新的父链接)。
PHP数组函数可能对此有所帮助。
答案 3 :(得分:0)
如果你想保持目前的做法,只是优化,你可以将查询包装在IF语句中。
喜欢:
if ( isset ( $parent_name_change )){
// run query
}