#mysql #foreign-keys
#mysql #внешние ключи
Вопрос:
В моей базе данных у меня есть 2 таблицы: сообщения и обновления. Эти 2 таблицы хранят некоторую информацию, например текст, И могут иметь 0, 1 или несколько параметров. Для хранения этих параметров у меня есть 2 другие таблицы: Messages_params и Updates_params. Эти 2 таблицы имеют одинаковые столбцы :
- ID
- ID_message/ID_update
- Клавиша
- raw_value (может быть null)
- ID_direct_reference (может быть нулевым)
Эти параметры могут быть либо: необработанное значение (сохраненное как переменные), в этом случае raw_value равно фактическому значению, а ID_direct_reference равно нулю, либо идентификатор того, что я называю «прямой ссылкой». Эти прямые ссылки представляют собой просто таблицы, содержащие имя класса PHP и которые могут иметь свои собственные параметры.
Итак, у меня есть 2 другие таблицы, содержащие эти прямые ссылки и их параметры: direct_reference (идентификатор, имя_класса) и direct_reference_params (идентификатор, ID_direct_reference, ключ, значение).
В принципе, я создаю эту систему, чтобы иметь динамические параметры для обновлений моего приложения и сообщений. Например, допустим, пользователю A понравилась фотография пользователя B. Для пользователя B создается обновление, в котором должно быть указано «{псевдопользователю A} нравится ваша фотография». Обновление создается немедленно, но доставляется в клиентское приложение только тогда, когда пользователь B находится в нем и запрашивает новые обновления. Если пользователь B вернется в приложение через час после создания обновления, И если пользователь A тем временем изменит свое псевдо, пользователь B получит обновление со старым псевдо пользователя A. Итак, в принципе, я хочу вычислить некоторые параметры обновления в момент их доставки (а не в момент их создания).
Когда доставляется обновление (или сообщение), мой сервер проверяет наличие прямых ссылок в своих параметрах; он вызывает определенный метод прямой ссылки classname
(через отражение PHP) и отправляет параметры прямой ссылки этому методу, чтобы класс знал, что возвращать.
Теперь возникает мой вопрос: я хочу, чтобы эти прямые ссылки удалялись, когда их владелец автоматически удаляется внешними ключами в mysql. Но, поскольку эти прямые ссылки теоретически могут содержаться в нескольких строках в нескольких таблицах (параметры сообщений и обновления и любые другие параметры, которые могут в них нуждаться), как я могу сказать mysql «Автоматически удалять строку прямой ссылки (и связанные с ней параметры DR), если ни одна строка ни в одной таблице больше не содержит ее идентификатора».
Спасибо, что прочитали этот сложный вопрос.
Ответ №1:
Вы действительно не можете. Внешние ключи просто не работают таким образом. Вы можете каскадировать удаления вниз по течению, но не вверх по течению.
Вместо этого вам следует подумать об использовании триггеров в «дочерних» таблицах, чтобы при удалении записи в этих таблицах вы могли запустить код для проверки и просмотра того, какие еще отношения родительский элемент имеет с другими дочерними элементами, а затем удалить его при необходимости.
CREATE TRIGGER cleanup_message AFTER DELETE on myTable
FOR EACH ROW
BEGIN
DELETE FROM messages
WHERE message.id = old.id
and messages.id not in (select ID from sometothertable)
and messages.id not in (select ID from yetanothertable)
END
Комментарии:
1. спасибо за ваш ответ, я не думал о триггерах mysql. единственная проблема, которую я нахожу, заключается в том, что, возможно, это решение может быть не оптимизировано с точки зрения производительности (mysql необходимо повторно просмотреть все мои таблицы, чтобы проверить наличие другой ссылки)
2. Только что выясненные триггеры mysql не работают с каскадным удалением внешнего ключа…
3. Я обнаружил, что триггеры MySQL не могут быть каскадированы, в отличие от PostgreSQL. Если я удалю участника, их сообщения будут автоматически удалены каскадом внешних ключей, но триггер не будет запущен…