Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> удаление в дочерних таблицах через внешние ключи, нужна небольшая подсказка 
V
    Опции темы
stalker2000
Дата 25.8.2015, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 29.7.2010

Репутация: нет
Всего: нет



Добрый день. Есть 3 таблицы, связанные между собой внешними ключами.
Код

CREATE TABLE IF NOT EXISTS `t1` (
  `id` int(11) NOT NULL auto_increment,
  `t1_text` varchar(222) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ;

CREATE TABLE IF NOT EXISTS `t1_to_t2` (
  `t1_id` int(11) NOT NULL,
  `t2_id` int(11) NOT NULL,
  PRIMARY KEY  (`t1_id`),
  KEY `t2_id` (`t2_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `t2` (
  `id` int(11) NOT NULL auto_increment,
  `t2_text` varchar(222) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

INSERT INTO `t1` (`id`, `t1_text`) VALUES (1, '1111'), (2, '2222'), (3, '3333'), (4, '4444'), (5, '5555'), (6, '6666'), (7, '7777'), (8, '8888'), (9, '9999'), (10, '0000');
INSERT INTO `t2` (`id`, `t2_text`) VALUES (1, '11111111'), (2, '22222222'),(3, '33333333');
INSERT INTO `t1_to_t2` (`t1_id`, `t2_id`) VALUES (1, 1), (2, 1), (3, 1), (4, 2), (5, 2), (6, 2), (7, 3), (8, 3), (9, 3),(10, 3);

ALTER TABLE `t1_to_t2` ADD CONSTRAINT `t1_to_t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE `t2` ADD CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`id`) REFERENCES `t1_to_t2` (`t2_id`) ON DELETE CASCADE ON UPDATE CASCADE;

получается вот так:
user posted image
В таблице t1_to_t2 - связь таблиц t1 и t2. Хочется, что бы при удалении записи в t1 удалялись соотв. записи в остальных. Всё так и работает, кроме досадной мелочи: после удаления в t1_to_t2 остаются хвосты. Например, если удалить из t1 запись с id=1, то в t1_to_t2 останутся строки:
Код

+-------+-------+
| t1_id | t2_id |
+-------+-------+
|     2 |     1 |
|     3 |     1 |
+-------+-------+

Можно ли решить эту проблему исключительно с помощью внешних ключей?

PM MAIL   Вверх
Akina
Дата 25.8.2015, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(stalker2000 @  25.8.2015,  19:39 Найти цитируемый пост)
Например, если удалить из t1 запись с id=1, то в t1_to_t2 останутся строки:
Код

+-------+-------+
| t1_id | t2_id |
+-------+-------+
|     2 |     1 |
|     3 |     1 |
+-------+-------+

А сфига бы должны удаляться записи с t1_id, НЕ равными t1.id удаляемой записи?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
stalker2000
Дата 25.8.2015, 19:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 29.7.2010

Репутация: нет
Всего: нет



Цитата(Akina @ 25.8.2015,  18:43)
А сфига бы должны удаляться записи с t1_id, НЕ равными t1.id удаляемой записи?

отсюда и вопрос, как сделать красиво...
PM MAIL   Вверх
tzirechnoy
Дата 25.8.2015, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 3
Всего: 16



Цитата
отсюда и вопрос, как сделать красиво...


Код
DELETE * FROM t1_to_t2;


Все лишние записи из t1_to_t2 после этого удалятся.
PM MAIL   Вверх
stalker2000
Дата 25.8.2015, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 29.7.2010

Репутация: нет
Всего: нет



Цитата(tzirechnoy @ 25.8.2015,  20:40)
Цитата
отсюда и вопрос, как сделать красиво...


Код
DELETE * FROM t1_to_t2;


Все лишние записи из t1_to_t2 после этого удалятся.

смешно. Тогда уже сразу TRUNCATE t1_to_t2

Начал делать триггерами, долбался два часа, оказывается mysql не поддерживает сработку триггера при изменениях по внешним ключам... Придётся отказаться от внешних ключей вообще и вешать всё в триггер на первую таблицу :(
PM MAIL   Вверх
_zorn_
Дата 26.8.2015, 06:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1076
Регистрация: 21.8.2007

Репутация: 2
Всего: 12



Цитата(stalker2000 @  26.8.2015,  02:13 Найти цитируемый пост)
отсюда и вопрос, как сделать красиво... 

Что значит красиво ?
Почему из таблицы t1_to_t2 должны удалится строки с t2_id=1 при удалении из таблицы t1 записи с id=1 ?

А ключи наверное нужно так
Код

ALTER TABLE `t1_to_t2` ADD CONSTRAINT `t1_to_t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE `t1_to_t2` ADD CONSTRAINT `t1_to_t2_ibfk_2` FOREIGN KEY (`t2_id`) REFERENCES `t2` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

PM MAIL   Вверх
Akina
Дата 26.8.2015, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(stalker2000 @  25.8.2015,  20:13 Найти цитируемый пост)
отсюда и вопрос

Ещё раз спрашиваю. 
Почему при удалении из t1 строки с t1.id=1 должны из t1_to_t2 удаляться строки с t1_id=2 и t1_id=3?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
stalker2000
Дата 26.8.2015, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 29.7.2010

Репутация: нет
Всего: нет



Цитата(Akina @ 26.8.2015,  09:21)
Цитата(Akina @  26.8.2015,  09:21 Найти цитируемый пост)
Ещё раз спрашиваю. 
Почему при удалении из t1 строки с t1.id=1 должны из t1_to_t2 удаляться строки с t1_id=2 и t1_id=3? 

объясню на рабочем примере.

в таблице t1 находятся некие правила
в таблице t2 находятся определённым образом обработанные тексты; обработка осуществляется с использованием правил из t1. Информация о том, какие правила использовались для обработки  каждой конкретной записи в t2 находится в таблице t1_to_t2. 

В данном примере в таблице t2:
для id=1 используются записи id=1,2,3 из t1;
для id=2 используются записи id=4,5,6 из t1;
для id=3 используются записи id=7,8,9,10 из t1;

задача: при удалении правила из t1 так же удалять обработанные этим правилом тексты из t2, и так же удалять записи в связующей таблице t1_to_t2

Сейчас ещё заметил ошибку в своём первом посте. В таблице t1_to_t2 индекс по полю t1_id не может быть PRIMARY, т.к. записи в нём могут повторяться. Правильно вот так:
Код

CREATE TABLE IF NOT EXISTS `t1_to_t2` (
  `t1_id` int(11) NOT NULL,
  `t2_id` int(11) NOT NULL,
  KEY `t1_id` (`t1_id`),
  KEY `t2_id` (`t2_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

PM MAIL   Вверх
Akina
Дата 26.8.2015, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Вы не понимаете сути референсных действий.

Для выполнения референсного действия (в данном случае удаления) необходимо, чтобы дочерняя таблица ссылалась на уникальный (первичный) ключ родительской. При невыполнении условия уникальности невозможно определить, на какую запись родителя ссылается дочка, соответственно невозможно определить, какие дочки требуют применения каскадного действия.

А т.к. у тебя
Цитата(stalker2000 @  26.8.2015,  11:40 Найти цитируемый пост)
В таблице t1_to_t2 индекс по полю t1_id не может быть PRIMARY, т.к. записи в нём могут повторяться.

то задача нерешаема.

Добавлено через 1 минуту и 9 секунд
Для обеспечения требуемого уровня поддержания целостности следует изолировать таблицы от клиента, и все действия по изменению (в данном случае удалению) данных выполнять через хранимую процедуру, которая реализует требуемую логику каскадного действия.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
stalker2000
Дата 26.8.2015, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 29.7.2010

Репутация: нет
Всего: нет



Цитата(Akina @  26.8.2015,  11:30 Найти цитируемый пост)
Для обеспечения требуемого уровня поддержания целостности следует изолировать таблицы от клиента, и все действия по изменению (в данном случае удалению) данных выполнять через хранимую процедуру, которая реализует требуемую логику каскадного действия.

я так и сделал, только не процедурой, а триггером
PM MAIL   Вверх
Akina
Дата 26.8.2015, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Триггер - не очень хорошо. Не каждая операция изменения данных вызывает срабатывание триггера. И будешь потом гадать, почему всё развалилось...


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
stalker2000
Дата 26.8.2015, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 29.7.2010

Репутация: нет
Всего: нет



Цитата(Akina @ 26.8.2015,  16:32)
Триггер - не очень хорошо. Не каждая операция изменения данных вызывает срабатывание триггера. И будешь потом гадать, почему всё развалилось...

Мне надо что-то делать только при удалении. Какие могут быть проблемы?
PM MAIL   Вверх
Akina
Дата 27.8.2015, 08:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 106
Всего: 454



Цитата(stalker2000 @  26.8.2015,  23:14 Найти цитируемый пост)
Какие могут быть проблемы? 

Такие же, как и сейчас - не-удаление связанных записей.

Решения вижу два.
Первое - уже озвученное, вынести логику в хранимую процедуру.
Второе - убрать каскадные операции, и выполнять удаление записей, потерявших связи, служебной процедурой по эвенту. Да, при этом в период с момента удаления до момента выполнения процедуры эвента в таблицах будут присутствовать "зависшие" записи, но логика запросов на получение данных не должна выбирать их в выходные наборы.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
stalker2000
Дата 27.8.2015, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 29.7.2010

Репутация: нет
Всего: нет



понятно, спасибо, учту
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MySQL | Следующая тема »


 




[ Время генерации скрипта: 0.0796 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.