Mysql: автоматически удаляет строку, если на нее больше нет ссылок (среди нескольких)

#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. Если я удалю участника, их сообщения будут автоматически удалены каскадом внешних ключей, но триггер не будет запущен…