Задать вопрос
kefiijrw
@kefiijrw

Реализация изменения записи в таблице связи с составным primary key?

Столкнулся с вроде бы стандартной ситуацией, но не могу найти некостыльное решение (или может просто я такой нежный). Ощущение, что всё очень просто и элементарно решается, а я недалекий орангутанг, который ничего не знает.



Есть две таблицы A и B, первичные ключи id — стандартные суррогатные эти самые INT NOT NULL AUTO_INCREMENT PRIMA…



Для реализации между ними связи «много ко многим» есть таблица связи A_B, состоящая из двух полей: a_id и b_id — внешних ключей таблиц A и B соответственно. Первичный ключ, что вроде логично, состоит из этой пары внешних ключей.



Есть пхпбыдлокодерская админка управления базой данных. В частности, страница редактирования связей между A и B. Если более конкретно, форма редактирования всех записей таблицы A_B с некоторым определенным a_id. В итоге получается около 20 записей на страницу, всё редактируется через инпуты с общим сабмитом.



ПРОБЛЕМА: php-скрипт, который обрабатывает форму по сабмиту, получает измененные связи и не знает, какими они были до редактирования, т.к. ключи, по которому они идентифицировались, изменились. То есть если пользователь меняет | a_id | b1_id | на | a_id | b2_id |, то скрипт знает, на что менять, но не знает, что изначально это была | a_id | b1_id |.



Я крепко задумался, нашел некоторые выходы, но они меня не устраивают:



1) хранить в форме hidden-поля с исходными значениями связей, отправлять их по сабмиту и по ним определять изменяемую запись БД. Не нравится: ощущение костыля; вопросы безопасности, хотя они, вообще говоря, волнуют меньше всего.

2) добавить в таблицу связи еще одно поле — суррогатный неменяемый id, по которому можно идентифицировать измененную связь. Как и в предыдущем пункте, хранить его в hidden-поле формы. Не нравится: см. предыдущий пункт + гнев богов реляционных моделей данных; необходимость лапатить структуру бд ради такой мелочи.

3) изменение = удаление + добавление. Зачищать все 20 записей и добавлять заново. Не нравится: ощущение костыля; удаление и добавление множества записей ради изменения единственной (это в данном случае 20, в другом будут все 120)



вразумите меня
  • Вопрос задан
  • 2927 просмотров
Подписаться 2 Оценить Комментировать
Решения вопроса 1
@niko83
перед сохранением достаём из базы то что есть по ключу a_id и
сравниваем с тем что пришло от пользователя. Используя array_diff() и прочие ухищрение находим те строки, которые нужно удалить и те которые нужно добавить. Если их кол-во одинаковое (если форма подразумевает функции обновления то так оно и будет), то можно заменить одним запросом на update.

Усложняется логика, но нет массового удаление как вы описали в пункте 3)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@Monca
Второй и третий варианты вполне жизненны.
Не написали, что за БД. Самое простое — поставить каскадное изменение (если есть). Или сделать каскад через триггеры (если есть).
Но если малой кровью, то третий вариант не плох, можно смело использовать.
Первый вариант совсем не годится.
Ответ написан
mmib
@mmib
и почему же гнев на вариант 2) если он так и напрашивается постановкой задачи. Да, это уже будет не 3-я нормальная форма, но Вам от этого хуже не будет. А обновлять подобные строки станет очень удобно. Главное не забыть сделать пару a_id, b_id уникальной

1) совсем костыльный вариант
3) если много данных будет медленно работать

избыточность данных в варианте 2) скорее всего наименьшее из трех зол
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы