Necromancing.
Правильный ответ: это зависит от того, какой механизм базы данных и какой инструмент управления.
Давайте сделаем пример: у
нас есть таблица отчета,
и у отчета может быть родитель (пункт меню, например категория),
и у этого родителя может быть родитель (например, Центр прибыли)
и так далее до бесконечности.
Самый простой пример стандартного рекурсивного отношения, как и для любой самоссылающейся сущности / иерархии.
В результате получается таблица SQL-Server:
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'dbo.FK_T_FMS_Reports_T_FMS_Reports') AND parent_object_id = OBJECT_ID(N'dbo.T_FMS_Reports'))
ALTER TABLE dbo.T_FMS_Reports DROP CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.T_FMS_Reports') AND type in (N'U'))
DROP TABLE dbo.T_FMS_Reports
GO
CREATE TABLE dbo.T_FMS_Reports
(
RE_UID uniqueidentifier NOT NULL
,RE_RE_UID uniqueidentifier NULL
,RE_Text nvarchar(255) NULL
,RE_Link nvarchar(400) NULL
,RE_Sort int NOT NULL
,RE_Status int NOT NULL
,PRIMARY KEY CLUSTERED ( RE_UID )
);
GO
ALTER TABLE dbo.T_FMS_Reports WITH CHECK ADD CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports FOREIGN KEY(RE_RE_UID)
REFERENCES dbo.T_FMS_Reports (RE_UID)
-- ON DELETE CASCADE -- here, MS-SQL has a problem
GO
ALTER TABLE dbo.T_FMS_Reports CHECK CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports
GO
Но у вас возникает проблема:
когда вам нужно удалить пункт меню со всеми его подменю, вы НЕ МОЖЕТЕ установить delete-cascade, потому что Microsoft SQL-Server не поддерживает рекурсивное каскадное удаление (с другой стороны, PostGreSQL делает [но только если graph не циклический], в то время как MySQL вообще не нравится такая структура таблиц, потому что она не поддерживает рекурсивные CTE).
Таким образом, вы как бы взрывают целостность / функциональность удаления, делая обязательным выполнение таких функций в своем собственном коде или в хранимой процедуре (если ваша СУБД поддерживает хранимые процедуры).
Это, несомненно, взорвет любой вид полностью автоматического динамического импорта / экспорта данных, потому что вы не можете ни просто выполнить оператор удаления для всех таблиц в соответствии с отношениями внешних ключей (не являющихся ссылками), ни сделать простой выбор * и создать вставку для каждой строки в произвольном порядке.
Например, когда вы создаете сценарий INSERT с использованием SSMS, тогда SSMS не получит внешний ключ и, таким образом, действительно создаст операторы вставки, которые будут вставлять записи с зависимостями, прежде чем он вставит родительский элемент зависимости, что приведет к ошибке с ошибкой потому что внешний ключ на месте.
Тем не менее, в надлежащих системах управления базами данных (таких как PostgreSQL), с надлежащим инструментарием, это не должно быть проблемой. Просто поймите, что если вы много платите за свою СУБД (я смотрю на вас, Microsoft; Oracle =?) И / или на ее пояс для инструментов, это не значит, что она запрограммирована правильно. И при этом OpenSource (например, MySQL) не делает вас невосприимчивым к таким замечательным мелочам.
Дьявол кроется в деталях, как гласит старая поговорка.
Не то чтобы вы не могли обойти такие проблемы, но я бы не стал этого рекомендовать, если ваша система будет сложной (например, 200+ таблиц).
Кроме того, в обычной коммерческой обстановке (как изображено Дилбертом) вам просто не дадут этого времени.
Гораздо лучшим подходом, хотя и более сложным, будет закрытие таблицы.
Это будет иметь дополнительный бонус, что он также работает на MySQL.
Как только вы реализуете функцию замыкания один раз, она будет работать в дополнительных местах практически за короткое время.