PHP обновление MYSQL много-ко-многим отношение
У меня есть отношение "многие ко многим", реализованное с таблицей ассоциаций в MySQL. У меня есть стол для детей и стол для родителей. У ребенка может быть несколько родителей, сохраненных в таблице ассоциаций parent_child_link с их идентификаторами.
дети могут быть обновлены через HTML-форму, родители находятся в HTML multi-select. Теперь мне нужно обновить запись в базе данных, но мое решение не очень эффективно. Вот в псевдокоде, что я do:
- обновить данные ребенка, где ид_дочернего_объекта=х
- удалить все текущие ассоциации в parent_child_link, где child_id=x
- вставить новые ассоциации
Это решение отлично работает, но когда родители не были изменены, например, было изменено только имя ребенка, тогда выполняются 2 ненужных запроса. Как избежать этих ненужных вопросов? Есть ли способ проверить, если родители в multi-select не изменился?
конечно, я мог бы просто игнорировать все эти хлопоты, потому что он уже работает, но мне очень нравится держать вещи как можно более эффективными.
4 ответов
попробуйте решить его в базе данных, а не на уровне приложения с помощью 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
EDIT: для вашего отношения "многие ко многим" вы можете использовать что-то вроде:
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
);
надеюсь, что это помогает.
у меня тот же вопрос и выяснил мое решение, когда я читал.
когда я готов обработать отправленные записи, я сначала делаю запрос, чтобы получить текущие ассоциации и вызвать этот массив $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
}
хотелось бы знать, считают ли другие это действительным решением.
ваше решение в порядке.
В вашем случае вы можете "оптимизировать" процесс, сделав запрос для извлечения родителей и проверки с помощью данных множественного выбора, если какие-либо изменения произошли.
Затем вы выполняете только два запроса delete и insert, если это необходимо. Аналогом является то, что когда вы фактически изменили родителей, тогда будет 3 запроса вместо 2.
Поэтому вы должны спросить вас, собираетесь ли вы очень часто изменять родителей. В этом случае вы должны придерживаться своего оригинальное решение, чтобы избежать дополнительного запроса SELECT.
Если вы думаете, что родители не будут обновляться очень часто, то вы можете пойти с вышеуказанным решением. При обновлении только дочерней информации выполняется только один запрос. При обновлении родителей выполняется 3 запроса.
Когда вы идете со вторым решением, запросы delete и insert также могут быть оптимизированы, чтобы выполнять только то, что требуется (только удалять родителей, которые больше не являются его родителями, и только вставлять нового родителя дюны.)
Для этого могут быть полезны функции массива PHP.
Если вы хотите сохранить текущий способ сделать это, но просто оптимизировать, вы можете обернуть запросы в операторы IF.
Как:
if ( isset ( $parent_name_change )){
// run query
}