Проверить наличие внешних связей
Проверить наличие внешних связей
Есть небольшая проблема...
Имеем 1 таблицу (далее - основная) с полем id и еще кучей других полей, далее есть еще N таблиц (дополнительные) связанных с таблицей 1 по полю id.
Задача такова: при удалении из дополнительной таблицы, если больше ни одна из дополнительных таблиц не содержит данного id то удалить запись с этим id из основной таблицы.
Пока нашел 2 решения:
1. Просто попробовать удалить, в случае чего (если есть связи по этому id) вывалится эксепшн и ничего не удалится. Мне кажется как-то грубо
2. Прогнать "select count(*) from ... where id = myid" по всем доп. таблицам, если везде 0 записей то удалить из основной. Это по моему как-то долго и еще нужно нагенерить запросов для каждой таблицы. Или может можно как-то одним запросом сделать? Пробовал "select count(*) from "Table1", "Table2" where "id" = 1" говорит ambiguous field name...
Есть ли способы проще?
Имеем 1 таблицу (далее - основная) с полем id и еще кучей других полей, далее есть еще N таблиц (дополнительные) связанных с таблицей 1 по полю id.
Задача такова: при удалении из дополнительной таблицы, если больше ни одна из дополнительных таблиц не содержит данного id то удалить запись с этим id из основной таблицы.
Пока нашел 2 решения:
1. Просто попробовать удалить, в случае чего (если есть связи по этому id) вывалится эксепшн и ничего не удалится. Мне кажется как-то грубо
2. Прогнать "select count(*) from ... where id = myid" по всем доп. таблицам, если везде 0 записей то удалить из основной. Это по моему как-то долго и еще нужно нагенерить запросов для каждой таблицы. Или может можно как-то одним запросом сделать? Пробовал "select count(*) from "Table1", "Table2" where "id" = 1" говорит ambiguous field name...
Есть ли способы проще?
-
- Заслуженный разработчик
- Сообщения: 1436
- Зарегистрирован: 15 сен 2005, 09:05
Re: Проверить наличие внешних связей
Просто и тупо пытайся удалить запись из основной таблицы и гаси исключение с помощью WHEN. Если подчиненных записей нет - она удалится. Если есть - никакие проверки не помогут.fmcoder писал(а):Задача такова: при удалении из дополнительной таблицы, если больше ни одна из дополнительных таблиц не содержит данного id то удалить запись с этим id из основной таблицы.
Есть ли способы проще?
Re: Проверить наличие внешних связей
Я бы ещё ПЕРЕД удалением подчинённой записи делал блокировку мастер-записи (через update или select ... for update with lock), чтоб другим транзакциям неповадно было.
Re: Проверить наличие внешних связей
Чего именно неповадно?Slavik писал(а):Я бы ещё ПЕРЕД удалением подчинённой записи делал блокировку мастер-записи (через update или select ... for update with lock), чтоб другим транзакциям неповадно было.
Re: Проверить наличие внешних связей
Делать тоже самое. Например, есть мастер-запись и две её подчинённые записи. Одна транзакция стартует и удаляет первую подчинённую запись, проверяет - ещё есть подчинённые записи, естественно удалять мастер-запись и не собирается. В это же время стартует другая транзакция и удаляет вторую подчинённую запись, проверка также не даёт удалить мастер запись, т.к. удаление, сделанное в первой транзакии для второй - не видны. Первая и вторая транзакции успешно коммитятся. В итоге, мастер-запись остаётся без подчинённых.WildSery писал(а):Чего именно неповадно?
Блокировка же мастер-записи даст по мордам второй конкурентной транзакции.
Re: Проверить наличие внешних связей
Чтобы так не было, удалять родителя надо отдельной транзакцией.Slavik писал(а):Например, есть мастер-запись и две её подчинённые записи. Одна транзакция стартует и удаляет первую подчинённую запись, проверяет - ещё есть подчинённые записи, естественно удалять мастер-запись и не собирается. В это же время стартует другая транзакция и удаляет вторую подчинённую запись, проверка также не даёт удалить мастер запись, т.к. удаление, сделанное в первой транзакии для второй - не видны. Первая и вторая транзакции успешно коммитятся. В итоге, мастер-запись остаётся без подчинённых.
Блокировка даст по мордам всем, в итоге ни одну дочернюю запись нельзя будет удалить, пока не отпустят. Хорошо ли это?Slavik писал(а):Блокировка же мастер-записи даст по мордам второй конкурентной транзакции.
Всем спасибо за ответы!
А что за WHEN? Информации по нему найти не смог, слишком общеупотребительное слово... Я так думаю это то что надо (гасить исключения), просто пытаться удалить, если получится - удалится, если нет то нет и никаких проблем.
Насчет lock и нескольких транзакций одновременно это врядли. У меня система расчитана на работу на одном компьютере (и сервер и клиент), а кол-во программ-клиентов где-то от 3-х до 12, и то удалять может только одна (максимум 3) из них, остальные читают или update'ят, поэтому тут думаю можно не бояться конфликтов.
А что за WHEN? Информации по нему найти не смог, слишком общеупотребительное слово... Я так думаю это то что надо (гасить исключения), просто пытаться удалить, если получится - удалится, если нет то нет и никаких проблем.
Насчет lock и нескольких транзакций одновременно это врядли. У меня система расчитана на работу на одном компьютере (и сервер и клиент), а кол-во программ-клиентов где-то от 3-х до 12, и то удалять может только одна (максимум 3) из них, остальные читают или update'ят, поэтому тут думаю можно не бояться конфликтов.
Искать нужно было конкретно в синтаксисе PSQL-блоков. Ловля исключений в процедурах/триггерах.fmcoder писал(а):А что за WHEN?
Например,
Код: Выделить всё
delete from Table1 where id=:id;
when any do begin
insert into log (id, val) values (:id, 'Not deleted');
end
Конфликтов чего? Ты ж сам правильно сказал, что исключение на невозможность удаления можно просто давить и всё.fmcoder писал(а):то удалять может только одна (максимум 3) из них, остальные читают или update'ят, поэтому тут думаю можно не бояться конфликтов.
Re: Проверить наличие внешних связей
Можно и так, хоть и остаётся некоторая вероятность облома, не связанного с наличием подчинённых записей.WildSery писал(а):Чтобы так не было, удалять родителя надо отдельной транзакцией.
Автор, похоже, блокировок не боитсяWildSery писал(а):Блокировка даст по мордам всем, в итоге ни одну дочернюю запись нельзя будет удалить, пока не отпустят. Хорошо ли это?
Re: Проверить наличие внешних связей
Какого например?Slavik писал(а):Можно и так, хоть и остаётся некоторая вероятность облома, не связанного с наличием подчинённых записей.
Не понял. Почему он не боится? Все боятсяSlavik писал(а):Автор, похоже, блокировок не боится
Re: Проверить наличие внешних связей
Сервер прилёг отдохнуть, сетка тоже устала...WildSery писал(а):Какого например?
Откуда ж я знаю. Говорит "можно не бояться конфликтов"...WildSery писал(а):Не понял. Почему он не боится? Все боятся